Unity3D 网络游戏框架(四、异步客户端Socket)参考连接:Socket 类 (System.Net.Sockets) | Microsoft Learn
在之前的代码中,我们了解了如何开发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类型的参数封装在了IAsyncResult 的AsyncState当中,将封装好的接口发送给我们的回调函数,举个例子:在BeginConnect当中,我们传入ConnectCallback和socket,当客户端要连接服务端的时候,执行我们的回调函数ConnectCallback并且把socket传了进去,在回调函数ConnectCallback当中用ar.AsyncState来取得我们的socket,然后每次执行完都要调用End...
在我们ReceiveCallback当中,又一次调用了BeginReceive这是递归调用我们的回调函数,保证客户端可以一直接收服务端消息
注意:操作Unity当中操作UI只能在主线程中,所以我这里写在了UPdate里面