当前位置: 首页 > article >正文

【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方法

二、本地服务器代码

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

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

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

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;
                    }                    

                    //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();
        }
    }
}

http://www.kler.cn/a/447633.html

相关文章:

  • 基础爬虫案例实战
  • LeetCode题练习与总结:预测赢家--486
  • CUDA编程 | 6.2 并发内核执行
  • VUE3+django接口自动化部署平台部署说明文档(使用说明,需要私信)
  • React图标库: 使用React Icons实现定制化图标效果
  • CLION中运行远程的GUI程序
  • 基于BigBangBigCrunch优化(BBBC)的目标函数求解算法matlab仿真
  • 【Rust自学】5.1. 定义并实例化struct
  • AtCoder Beginner Contest 385(A~E)题解
  • OpenEuler22.04配置zookeeper+kafka三节点集群
  • 前端滚动条自定义样式
  • 渗透测试-前后端加密分析之RSA+AES
  • 使用Python实现无人机自动导航系统:探索智能飞行的奥秘
  • ansible剧本快速上手
  • 汽车IVI中控开发入门及进阶(三十八):手机投屏HiCar开发
  • golang rocketmq保证数据一致性(以电商订单为例)
  • JAVA前端开发中type=“danger“和 type=“text“的区别
  • 《计算机组成及汇编语言原理》阅读笔记:p28-p47
  • 修改npm镜像源
  • MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
  • Sora技术报告【官方版】
  • 【算法】——双指针(上)
  • Redis 多实例配置说明
  • 鸿蒙开发——关系型数据库的基本使用与跨设备同步
  • Vue简介和项目构建
  • Java详细总结