Unity3d C# Socket异步发送与接收数据 您所在的位置:网站首页 receive被动 Unity3d C# Socket异步发送与接收数据

Unity3d C# Socket异步发送与接收数据

2023-08-23 00:24| 来源: 网络整理| 查看: 265

在网络游戏开发中,一些游戏需要使用长连接的方式进行网络通信,即使用Socket建立长连接。那么在Unity3d中,如何使用C#与服务端建立长连接呢?为什么 要说使用异步呢?我们知道,在Unity3d中,每个游戏画面的播放都是以帖的概念循环播放的。而且只能在UI线程中播放,在其它线程不可以操作UI有关的东西,这都是网络通信需要解决的问题。

使用Socket创建连接

众所周知,在游戏客户端启动之后,一定有一个时机是创建网络连接的,比如一般是选游戏大区这后,或用户点击进入游戏时,这都是由UI层触发点击和创建网络连接的。但是网络连接是一个IO阻塞操作,如果直接使用Socket的同步方法,会卡住当前UI线程,导致游戏画面出现卡顿现象。所以要么使用协程,要么便需要使用异步创建连接。为了方便创建socket连接,这里使用异步连接方式。如下面代码所示:

public void ConnectServer() { this.Close(); try { _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); SocketAsyncEventArgs args = new SocketAsyncEventArgs();//创建连接参数对象 this.endPoint = new IPEndPoint(IPAddress.Parse(host), port); args.RemoteEndPoint = this.endPoint; args.Completed += OnConnectedCompleted;//添加连接创建成功监听 _socket.ConnectAsync(args); //异步创建连接 } catch(Exception e) { Debug.Log("服务器连接异常:" + e); } } private void OnConnectedCompleted(object sender,SocketAsyncEventArgs args) { try { ///连接创建成功监听处理 if (args.SocketError != SocketError.Success) { //通知上层连接失败 CompleteConnectServerHandler?.Invoke(ConnectedStatus.ConnectFailed); } else { Debug.Log("网络连接成功线程:" + Thread.CurrentThread.ManagedThreadId.ToString()); //通知上层连接创建成功 CompleteConnectServerHandler?.Invoke(ConnectedStatus.ConnectedSucess); StartReceiveMessage(); //启动接收消息 } } catch(Exception e) { Debug.Log("开启接收数据异常" + e); } } 发送消息

一般来说,消息的发送都是UI层触发的,比如点击某个按钮,执行了某个操作,就会向服务器获取或保存数据。所以也需要使用协程或异步的方式发送消息,这里使用异步的方式。如下面代码所示:

public void SendToServer(byte[] data) { try { if (_socket == null || !_socket.Connected) { Debug.Log("socket未连接,发送消息失败"); return; } //创建发送参数 SocketAsyncEventArgs sendEventArgs = new SocketAsyncEventArgs(); sendEventArgs.RemoteEndPoint = endPoint; //设置要发送的数据 sendEventArgs.SetBuffer(data, 0, data.Length); //异步发送数据 _socket.SendAsync(sendEventArgs); } catch(Exception e) { Debug.Log("发送数据异常:" + e); } }

由于Socket制作是一种非常底层的操作,所以这里直接发送byte[],具体发送什么样的数据,由应用层决定。

接收数据

由于我们使用的是Socket自带的异步创建连接,发送数据,所以接收数据也是在socket的异步线程中。如下面代码所示:

private void StartReceiveMessage() { //启动接收消息 SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs(); //设置接收消息的缓存大小,正式项目中可以放在配置 文件中 byte[] buffer = new byte[1024 * 512]; //设置接收缓存 receiveArgs.SetBuffer(buffer, 0, buffer.Length); receiveArgs.RemoteEndPoint = this.endPoint; receiveArgs.Completed += OnReceiveCompleted; //接收成功 _socket.ReceiveAsync(receiveArgs);//开始异步接收监听 } public void OnReceiveCompleted(object sender,SocketAsyncEventArgs args) { try { Debug.Log("网络接收成功线程:" + Thread.CurrentThread.ManagedThreadId.ToString()); if (args.SocketError == SocketError.Success && args.BytesTransferred > 0) { //创建读取数据的缓存 byte[] bytes = new byte[args.BytesTransferred]; //将数据复制到缓存中 Buffer.BlockCopy(args.Buffer, 0, bytes, 0, bytes.Length); if(ReceiveSocketDataHandler == null) { Debug.Log("没有处理接收消息的事件 "); } //接收数据成功,调上层处理接收数据的事件 ReceiveSocketDataHandler?.Invoke(bytes); //再次启动接收数据监听,接收下次的数据。 StartReceiveMessage(); } else { CompleteConnectServerHandler(ConnectedStatus.Disconnect); } } catch(Exception e) { Debug.Log("接收数据异常:" + e); } }

接收数据的方法会在连接创建成功时调一次,它一直监听服务器的数据到来。当接收到服务器的数据时,我们会调用上层处理数据的事件 ,即ReceiveSocketDataHandler?.Invoke(bytes); ,首先要做的就是对接收的数据进行断包和粘包处理。这个在下篇文章中再说。

详细的代码,可以参考项目源码:http://www.xinyues.com/h-nd-195.html#_np=2_627 可以关注微信公众号,及时接收文章推送 欢迎关注微信公号



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有