使用ToLuaFramework实现Socket连网消息的收发(九)

本文详细介绍使用LuaFramework框架实现Lua客户端与服务器的联网消息收发过程,包括连接服务器、发送与接收消息的具体步骤及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

「前言」

现在的游戏基本上都是联网,所以联网真的很重要。所以这篇博客主要讲述关于Lua如何实现联网消息的收发。

我们直接使用LuaFramework框架自带的网络模块,去连接服务器,进行消息的收发,LuaFramework框架已经做好了消息协议号和粘拆包,这些都不用我们管,直接调用即可,所以我们只负责发和收就OK了。

消息的收发可以分为一下几个步骤:

● 绑定IP端口,进行连接
● 连接成功,发送信息
● 设置回调,进行接收
● 按钮点击,循环收发

LuaFramework的网络模块:

● NetworkManager「网络管理」
● SocketClient 「客户端」
● ByteBuffer「字节缓冲」
● Converter「转换器」
● Protocal 「消息协议」

绑定IP端口,进行连接

发起连接是联网的第一步,框架的发起连接有两个地方,第一个就是Mian脚本主函数入口,第二个就是Gmae脚本里
的Game.OnInitOK()方法里。Mian.lua脚本代码如下:

--主入口函数。从这里开始lua逻辑
require "Network"

function Main()
		print("主入口函数。从这里开始lua逻辑")

	local LuaHelper = LuaFramework.LuaHelper
	local networkMgr = LuaHelper.GetNetManager()
	local AppConst = LuaFramework.AppConst
	--设置端口号
    AppConst.SocketPort = 10004;
    --设置id
    AppConst.SocketAddress = "127.0.0.1";
    --开始连接服务器
	networkMgr:SendConnect();
end

连接成功,发送信息

服务器在收到信息后会自动LuaFramework会调用NetworkOnSocket方法,在接收到连接成功的信息时,我们直接给服务器在发一条信息,用来测试。
代码如下:

--Socket消息--
function Network.OnSocket(key, data)
	if key == 101 then
		LuaFramework.Util.Log("连接服务器成功!");		
		 Send()
	end
end

function Send()
    --拼接数据
     LuaFramework.Util.Log('开始发送数据');    
    local buffer = LuaFramework.ByteBuffer.New();
    buffer:WriteShort(Protocal.Message);
    buffer:WriteString("追求梦想,壹叶成名!");
    --进行发送
    local LuaHelper = LuaFramework.LuaHelper
    local networkMgr = LuaHelper.GetNetManager()
    networkMgr:SendMessage(buffer);
    LuaFramework.Util.Log('数据发送完毕');    
end	

设置回调,进行接收

LuaFramework框架在Network.lua脚本的Network.Start() 的方法里已经为我们设计好了消息回调,当收到不同的消息协号时,会调用不同的方法。

function Network.Start() 
    logWarn("Network.Start!!");
     --表示当收到101协议(Protocal.Connect)时,回调Network.OnConnect方法
    Event.AddListener(Protocal.Connect, this.OnConnect); 
    --表示当收到104协议(Protocal.Message)时,回调Network.OnMessage方法
    Event.AddListener(Protocal.Message, this.OnMessage); 
    --表示当收到102协议(Protocal.Exception)时,回调Network.Exception方法
    Event.AddListener(Protocal.Exception, this.OnException); 
    --表示当收到103协议(Protocal.Disconnect)时,回调Network.Disconnect方法
    Event.AddListener(Protocal.Disconnect, this.OnDisconnect); 
end

下面是Protocal 「消息协议」脚本:

Protocal = {
	Connect		= '101';	--连接服务器
	Exception   = '102';	--异常掉线
	Disconnect  = '103';	--正常断线   
	Message		= '104';	--接收消息
}

注意事项:这个脚本LuaFramework框架已经为我们创建好,在Common-Protocal.lua下,我们不需要创建,只需要直接使用就行。

如果你想自己创建脚本进行关联,只需要引用 Event = require ‘events’ 进行设计回调就可以解决
参考如下:

require "Logic/Network"
Event = require 'events'

function Start()
    --表示当收到101协议(Protocal.Connect)时,回调Network.OnConnect方法
    Event.AddListener(Protocal.Connect, Network.OnConnect); 
    --表示当收到104协议(Protocal.Message)时,回调Network.OnMessage方法
    Event.AddListener(Protocal.Message, Network.OnMessage); 
end

在回调方法里,我们可以看到信息的接收是通过Network.OnMessage方法进行接收的,所以我们只需要在Network.OnMessage方法进行消息接收的处理即可。
如下:

function Network.OnMessage(buffer) 
    LuaFramework.Util.Log('调用OnMessage方法,接收到消息');
    local str = buffer:ReadString();
    LuaFramework.Util.Log('收到的字符串:'..str);
 end

到这Lua客户端的连接,收消息,发消息就基本完成了。因为需要测试,所以就写了个C#简单的支持多连接,和循环接收的服务器,因为后面要测试点击按钮循环发送要用到。参考如下:

负责连接的脚本

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;

namespace LuaServer
{
    class Program
    {
        /// <summary>
        /// 所有客户端管理列表
        /// </summary>
        public static List<ClientSocketController> AllClientList = new List<ClientSocketController>();
        static void Main(string[] args)
        {
            Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
            IPEndPoint ipEp = new IPEndPoint(ipAdr, 10004);
            Console.WriteLine("正在绑定端口号");
            listenfd.Bind(ipEp);
            Console.WriteLine("端口号绑定完成,开启监听");
            listenfd.Listen(100);
            Console.WriteLine("服务器启动成功");
            while (true)
            {
                try
                {
                    Console.WriteLine("等待连接...");
                    Socket connfd = listenfd.Accept();
                    //创建客户端
                    ClientSocketController client = new ClientSocketController(connfd);
                    //把这个客户端添加进客户端管理列表
                    AllClientList.Add(client);
                    Console.WriteLine("当前有" + AllClientList.Count+"个用户连接");
                }
                catch (Exception e)
                {
                    //打印错误原因 
                    Console.WriteLine(e.ToString());
                }

            }
        }
    }
}

客户端控制器

using System;
using System.Net.Sockets;
using System.Threading;
/// <summary>
/// 客户端控制器
/// </summary>
namespace LuaServer
{
    class ClientSocketController
    {
        /// <summary>
        /// 用户链接的通道
        /// </summary>
        private Socket clientSocket;
        /// <summary>
        /// 接收线程
        /// </summary>
        Thread receiveThread;
        public ClientSocketController(Socket socket)
        {
            clientSocket = socket;
            //启动接收的方法
            //开始收的线程
            receiveThread = new Thread(ReceiveFromClient);
            //启动收的线程
            receiveThread.Start();
        }
        void ReceiveFromClient()
        {
            Console.WriteLine("收到了客户端发来的消息...");
            try
            {
                //开始接收
                while (true)
                {
                    byte[] readBuffer = new byte[10004];
                    //开启接收
                    int ByteLenght = clientSocket.Receive(readBuffer);
                    if (ByteLenght > 0)
                    {
                        Console.WriteLine("服务器接收完毕!!");
                        string showByteString = "";
                        //把字节进行string拼接
                        for (int i = 0; i < ByteLenght; i++)
                        {
                            int b = (int)readBuffer[i];
                            showByteString += b.ToString() + " ";
                        }
                        Console.WriteLine("服务器接收字节流:" + showByteString);
                        //解析消息  消息长度+消息协议号+消息内容
                        Int16 messageLen = BitConverter.ToInt16(readBuffer, 0);
                        Int16 protocal = BitConverter.ToInt16(readBuffer, 2);
                        Int16 strLen = BitConverter.ToInt16(readBuffer, 4);
                        string msgContent = System.Text.Encoding.UTF8.GetString(readBuffer, 6, strLen);
                        Console.WriteLine("<服务器接收>长度:" + messageLen);
                        Console.WriteLine("<服务器接收>协议号:" + protocal);
                        Console.WriteLine("<服务器接收的消息内容>字符串:" + msgContent);
                        //收到之后把收到的信息,立即回复过去
                        byte[] writeBuffer = new byte[ByteLenght];
                        Array.Copy(readBuffer, writeBuffer, ByteLenght);
                        clientSocket.Send(writeBuffer);

                        Console.WriteLine("\n"+"服务器把这条消息回复给客户端。");
                        Console.WriteLine("服务器发送信息完毕!");
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("e.ToString" + e.ToString());
            }
        }

    }
}

让我们开启服务器,运行起来测试一下:

在这里插入图片描述

我们可以看到客户端成功的连上了服务器,而服务器也成功的收到了客户端的消息,并且又把消息回发给了客户端,客户端收到消息后检索协议号为104,回调用了Network.OnMessage方法,并且进行消息的打印输出。

同时我们也可以看到,服务端收到的信息。字节流的前两位“34 0”表示消息长度为34字节,紧跟着的“104 0”代表协议号104。在字符串的封装中(buffer:WriteString),程序会先在buffer中添加字符串的长度,最后才是字符串的内容。“30 0”表示“追求梦想,壹叶成名!”。

总的来说,可以理解为 长度+协议号+字符串

现在是不是就能正常的使用Lua进行联网收发消息了呢,加个按钮,可以尝试一下,当然也可以扩展下服务器。

按钮发送的话就不过多介绍了,详见lua按钮事件。

有好的想法可以自己尽情尝试哦。

努力积才能,壹叶便成名。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铸梦xy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值