Unity3D 网络游戏框架(四、异步客户端Socket)

在之前的代码中,我们了解了如何开发Socket网络通讯的代码,但是程序会阻塞,这篇我们来介绍如何开发异步Socket。

首先我们还是先查看一下微软官方文档的API了解下面的几个方法:

1、Socket.BeginConnect()

2、Socket.EndConnect()

3、Socket.BeginReceive()

4、Socket.EndReceive()

5、Socket.BeginSend()

6、SocketEndSend()

参考连接:Socket 类 (System.Net.Sockets) | Microsoft Learn

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using UnityEngine.UI;
using System.Text;
using System;

public class Client : MonoBehaviour
{
    Socket socket;
    public InputField InputField;
    public Text text;
    /// <summary>
    /// 接收缓冲区
    /// </summary>
    byte[] readBuff=new byte[1024];
    string receiveStr = "";
    /// <summary>
    /// 连接
    /// </summary>
    public void Connect()
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socket.BeginConnect("127.0.0.1", 8888, ConnectCallback, socket);
    }
    /// <summary>
    /// 连接回调
    /// </summary>
    /// <param name="ar"></param>
    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndConnect(ar);
            Debug.Log("连接成功");
            socket.BeginReceive(readBuff, 0, 1024, 0, ReceiveCallback, socket);
        }
        catch (SocketException ex)
        {
            Debug.Log("客户端连接失败" + ex.ToString());
        }
    }
    /// <summary>
    /// 接收回调
    /// </summary>
    /// <param name="ar"></param>
    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket = ar.AsyncState as Socket;
            int count = socket.EndReceive(ar);
            string s=Encoding.UTF8.GetString(readBuff,0,count);
            receiveStr = s + "\n" + receiveStr;
            
            socket.BeginReceive(readBuff, 0, 1024, 0, ReceiveCallback, socket);
        }
        catch (SocketException ex)
        {
            Debug.Log("客户端接收失败" + ex.ToString());
        }
    }

    /// <summary>
    /// 发送
    /// </summary>
    public void Send()
    {
        //发送
        string sendStr = InputField.text;
        byte[] sendBytes = Encoding.UTF8.GetBytes(sendStr);
        socket.BeginSend(sendBytes, 0, sendBytes.Length, 0, SendCallback, socket);

        
    }
    /// <summary>
    /// 发送回调
    /// </summary>
    /// <param name="ar"></param>
    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            Socket socket =ar.AsyncState as Socket;
            int count=socket.EndSend(ar);
            Debug.Log("发送成功" + count);
        }
        catch (SocketException ex)
        {
            Debug.Log("发送失败" + ex.ToString());
        }
    }
    private void Update()
    {
        text.text = receiveStr;
    }
}

try...catch...是C#当中处理异常的结构,程序正常执行try里面,如果出现异常,那么执行catch

我们从这节用到的异步方法就可以看出来一个Begin...就对应一个End...,而且Begin...的参数都有一个回调函数和一个Object类型的参数,而且我们的每一个回调函数都有一个IAsyncResult类型的参数而我们在Begin...中把这个Object类型的参数封装在了IAsyncResultAsyncState当中,将封装好的接口发送给我们的回调函数,举个例子:BeginConnect当中,我们传入ConnectCallbacksocket,当客户端要连接服务端的时候,执行我们的回调函数ConnectCallback并且把socket传了进去,在回调函数ConnectCallback当中用ar.AsyncState来取得我们的socket,然后每次执行完都要调用End...

在我们ReceiveCallback当中,又一次调用了BeginReceive这是递归调用我们的回调函数,保证客户端可以一直接收服务端消息

注意:操作Unity当中操作UI只能在主线程中,所以我这里写在了UPdate里面

猜你喜欢

转载自blog.csdn.net/qq_39596597/article/details/127530765