目录
一、客户端代码
二、本地服务器代码
三、解决服务器无法多次接收客户端消息问题
一、客户端代码
连接本地服务器127.0.0.1:2012端口(如何创本地服务器,放最后说),连接成功后会回调
协议号Connect是101,其他如下,将这个Connect协议号和数据(空的字节流)放入一个mEvents队列,等待Update执行(目的应该是回到主线程才执行回调,避免一些问题)
这里Update方法就是Monobehaviour的生命周期Update,它简单地遍历队列逐个出队派发事件“DISPATCH_MESSAGE”去到如下
再回到调用lua的Network.OnSocket方法并且将 buffer.Key(协议号 101) 和 buffer.Value(空) 数据传递。
Network.OnSocket继续派发协议号作为事件名,执行OnConnect方法,至此完成一整套连接流程
其他相关的事件可以查如下找到相关的代码
由于我们lua侧仅写了1个消息协议号'104' 所以本地服务器代码也是要用104作为协议号传递,不然接收消息检测不到是104就无法正常通过消息派发并执行到对应的lua消息回调代码。
接收消息回调
TestProtoType有很多种传递消息的方式,项目默认使用ProtocalType.BINARY
好绕,最终是到了上面的WriteMessage方法,发送是以"消息长度"+"消息内容"为一条字节流传递到服务器,执行完后回调OnWrite方法
二、本地服务器代码
using System;
using System.Net;
using System.Net.Sockets;namespace SimpleNet
{class Program{static void Main(string[] args){Console.WriteLine("Hello World!");//Socket tcpSocket listenfd = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);//bindIPAddress ipAdr = IPAddress.Parse("127.0.0.1");IPEndPoint ipEp = new IPEndPoint(ipAdr, 2012);listenfd.Bind(ipEp);//listenlistenfd.Listen(0);Console.WriteLine("启动服务器成功");while (true){//AcceptSocket connfd = listenfd.Accept();Console.WriteLine("服务器Accept");//Recv 测试byte[] readBuff = new byte[100];int count = connfd.Receive(readBuff);//steamstring showStr = "";for(int i = 0; i< count; i++){int b = (int)readBuff[i];showStr += b.ToString() + " ";}Console.WriteLine("字节流:" + showStr);//解析Int16 msgLen = BitConverter.ToInt16(readBuff, 0);Int16 protocal = BitConverter.ToInt16(readBuff, 2);Int16 strLen = BitConverter.ToInt16(readBuff, 5);//具体还要看字节流输出来读取第几个字节是长度,若读错了下一行会报错string str = System.Text.Encoding.UTF8.GetString(readBuff, 6, strLen);Console.WriteLine("消息长度:" + msgLen);Console.WriteLine("协议号:" + protocal);Console.WriteLine("字符串:" + str);//send 原样返回byte[] writeBuff = new byte[count];Array.Copy(readBuff, writeBuff, count);connfd.Send(writeBuff);}}}
}
客户端接收到服务器消息的打印,服务器是直接将客户端的消息拷贝了一份再发送给客户端。
跑代码时发现有些lua报错:FindChild相关不存在
--初始化面板--
function MessagePanel.InitPanel()--this.btnClose = transform:FindChild("Button").gameObject; --bug代码 FindChild是不存在的接口...this.btnClose = transform:Find("Button").gameObject;
end
三、解决服务器无法多次接收客户端消息问题
测试发现上面的服务器代码不支持多次发送和接收消息,可以修改为如下服务器代码解决:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;namespace SimpleNet
{class Program{static async Task Main(string[] args){SimpleTcpServer server = new SimpleTcpServer("127.0.0.1", 2012);await server.StartAsync(); }}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;namespace SimpleNet
{public class SimpleTcpServer{private TcpListener _listener;private string _ip;private int _port; public SimpleTcpServer(string ip, int port){_ip = ip;_port = port;}public async Task StartAsync(){_listener = new TcpListener(IPAddress.Parse(_ip), _port);_listener.Start();Console.WriteLine($"Server started on port {_port}.");while (true){TcpClient client = await _listener.AcceptTcpClientAsync();_ = HandleClientAsync(client);}}private async Task HandleClientAsync(TcpClient client){NetworkStream stream = client.GetStream();byte[] readBuff = new byte[1024];while (true){try{int count = await stream.ReadAsync(readBuff, 0, readBuff.Length);if (count == 0) // Client disconnected{break;} //steamstring showStr = "";for (int i = 0; i < count; i++){int b = (int)readBuff[i];showStr += b.ToString() + " ";}Console.WriteLine("字节流:" + showStr);//解析Int16 msgLen = BitConverter.ToInt16(readBuff, 0);Int16 protocal = BitConverter.ToInt16(readBuff, 2);Int16 strLen = BitConverter.ToInt16(readBuff, 5);string str = System.Text.Encoding.UTF8.GetString(readBuff, 7, strLen);Console.WriteLine("消息长度:" + msgLen);Console.WriteLine("协议号:" + protocal);Console.WriteLine("字符串:" + str);//send 原样返回byte[] writeBuff = new byte[count];Array.Copy(readBuff, writeBuff, count);await stream.WriteAsync(writeBuff, 0, writeBuff.Length);}catch (Exception ex){Console.WriteLine("Error: " + ex.Message);break;}}client.Close();}public void Stop(){_listener.Stop();}}
}