【LuaFramework】服务器模块相关知识

目录

一、客户端代码

二、本地服务器代码

三、解决服务器无法多次接收客户端消息问题


一、客户端代码

连接本地服务器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方法

二、本地服务器代码

cs 复制代码
using System;
using System.Net;
using System.Net.Sockets;

namespace SimpleNet
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            //Socket  tcp
            Socket listenfd = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            //bind
            IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
            IPEndPoint ipEp = new IPEndPoint(ipAdr, 2012);
            listenfd.Bind(ipEp);
            //listen
            listenfd.Listen(0);
            Console.WriteLine("启动服务器成功");
            while (true)
            {
                //Accept
                Socket connfd = listenfd.Accept();
                Console.WriteLine("服务器Accept");
                //Recv 测试
                byte[] readBuff = new byte[100];
                int count = connfd.Receive(readBuff);
                //steam
                string 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

三、解决服务器无法多次接收客户端消息问题

测试发现上面的服务器代码不支持多次发送和接收消息,可以修改为如下服务器代码解决:

cs 复制代码
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();                       
        }
    }
}
cs 复制代码
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;
                    }                    

                    //steam
                    string 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();
        }
    }
}
相关推荐
两水先木示1 天前
【LuaFramework】LuaFramework_UGUI_V2框架学习
学习·unity·lua·luaframework·tolua
类人_猿1 年前
ToLua使用原生C#List和Dictionary
c#·list·dictionary·luaframework