本篇主要是分享基于unity的客户端socket网络通信方案。关于服务器的c#-socekt搭建放在了这里《基于C#的Tcp服务端通信》。其中关于socekt粘包断包的处理放在这里分享了《C# socket粘包断包处理》。
目录
整体设计
TcpClient
连接建立
消息发送
消息接收
关闭连接
完整代码
TcpClientMgr-业务处理
消息发送
消息接收
心跳和心跳超时
消息等待和超时
完整代码
整体设计
如图所示,一共采用了两层封装来处理整个客户端的逻辑。
首先TcpClient脚本只处理最基础的连接建立,消息的发送和接收。
TcpClientMgr管理和穿件TcpClient。在利用好连接建立,消息收发的基础上再处理业务上的需求:心跳、消息等待、事件传递等。
TcpClient
该层分为四个部分:
- 连接建立
- 消息发送
- 消息接收
- 关闭连接
连接建立
连接的创建这块采用的是异步连接Socket.ConnectAsync,并且通过Timer来处理连接超时的情况。
// 创建套接字
mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SocketAsyncEventArgs connectArgs = new SocketAsyncEventArgs();
connectArgs.UserToken = mClientSocket;
// 设置ip和端口号
connectArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(strIP), intPort);
// 设置完成回调
connectArgs.Completed += new EventHandler<SocketAsyncEventArgs>(OnConnect);
// 启动异步连接
mClientSocket.ConnectAsync(connectArgs);
超时的设计是,当开启异步连接的同时创建一定时器,定时器3秒之后执行。执行的内容为关闭连接。若期间连接上了则将定时器任务关闭。
// 连接超时定时器
System.Timers.Timer waitTimeOut;
// 设置超时
waitTimeOut = new System.Timers.Timer();
waitTimeOut.AutoReset = false;
waitTimeOut.Elapsed += OnConnectTimeOut;
waitTimeOut.Interval = 3000;
waitTimeOut.Start();
// 超时处理
private void OnConnectTimeOut(object sender, System.Timers.ElapsedEventArgs e)
{
if (mClientSocket != null && !mClientSocket.Connected)
{
FDebug.LogError("客户端连接超时");
Close();
}
}
连接成功之后就可以开启发送和接收任务了(线程),若连接收到的状态不是Success则执行连接失败的回调方法。
private void OnConnect(object sender, SocketAsyncEventArgs e)
{
// 终止超时设置
waitTimeOut.Stop();
if (e.SocketError == SocketError.Success)
{
// 开启发送线程
// 开启接收线程
// 发送一个连接请求
SendConnect();
FDebug.Log("客户端连接成功!");
}
else
{
FDebug.LogError("客户端连接失败"+e.SocketError.ToString());
mFnOnConnectFailed?.Invoke((int)e.SocketError);
}
}
中间有一个处理是SendConnect(),是给服务器推送一条连接协议。这里面的设计方案是,若服务器收到并返回一个连接协议,才将我们的连接状态标记改为true。
业务层TcpClientMgr的处理都依赖于这个标记为true。主要是为了确保我们的消息接发正常再跑业务逻辑。
消息发送
设置一个消息发送队列
外部只管向队列中放入我们约定的消息结构TcpData
内部开启一个线程不停的从队列中取得数据并通过socket发送出去
关于TcpData的定义可以参考一下这里《基于C#的Tcp服务端通信》