Untiy轻量级网络开发-Tnet客户端服务器编程

来源:互联网 发布:速拓必达医疗器械软件 编辑:程序博客网 时间:2024/05/22 20:28

在我们的项目实践中,需要对自定义的一些数据包进行处理

在这里介绍在unity平台上使用tnet网络引擎实现客户端与服务器中的数据交互

我在这里以登录注册功能来介绍tnet的使用


开发工具:VS(VS2012)(脚本编辑、生成服务器端)

    Unity(Unity5.x) (客户端)

    LitJson              (将类对象转化为json数据,方便网络数据的传输)


【客户端】

首先下载tnet源码点击打开链接

其中我提供了完整的工程项目源码


将源码导入到unity中


首先新建一个自定义C#脚本,用来在客户端数据的发送与接收进行处理

DateManager.cs

using UnityEngine;using System.Collections;using System.Collections.Generic;using System;using LitJson;using System.IO;using GameDate;public class ReceiveMessage{    /// <summary>    /// 服务器转发的后的处理    /// </summary>    /// <param name="reader"></param>    public static void Receive(BinaryReader reader)    {        string strName=reader.ReadString();        switch (strName)        {            case "注册":                SendRegisred.DictionaryForCallBack[strName](reader.ReadBoolean());                break;            case "登录":                SendLogin.DictionaryForCallBack[strName](JsonMapper.ToObject<RoleInfo>(reader.ReadString()));                break;        }    }}/// <summary>/// 写出可以让客户端轻松调用的通讯方法/// </summary>/// <typeparam name="T1">发送类</typeparam>/// <typeparam name="T2">返回值(也可以是类/// )</typeparam>public class SendMessageBase<T1,T2>{    /// <summary>    /// 当构造该对象时,需要制定功能名称    /// </summary>    /// <param name="str"></param>    public SendMessageBase(string str)    {        functionName = str;    }    /// <summary>    /// 记录需要执行的功能名称    /// </summary>    public string functionName;    /// <summary>    ///Action<T2> 存储回调函数,使用时需要引用using System头文件    ///Dictionary  存储回调函数的字典(key-value形式),使用时需要引用using System.Collections.Generic头文件    /// </summary>    public static Dictionary<string, Action<T2>> DictionaryForCallBack = new Dictionary<string, Action<T2>>();    public void Send(T1 messageClass,Action<T2> callBackFunction)    {        //发送过去的类,需要转化为json,经过封装后的类才能再发送        string messageStr = JsonMapper.ToJson(messageClass);        //将回调函数保存下来        if (DictionaryForCallBack.ContainsKey(functionName))        {            DictionaryForCallBack[functionName] = callBackFunction;        }        else        {            DictionaryForCallBack.Add(functionName,callBackFunction);        }        //发送数据        if (TNManager.isConnected)        {            //开始发送            BinaryWriter write = TNManager.BeginSend(TNet.Packet.SelfServerPacket);            write.Write(functionName);            write.Write(messageStr);            //结束发送            TNManager.EndSend();        }    }}public class SendRegisred : SendMessageBase<UserInfo, bool>{    public  SendRegisred():base("注册")    {    }}public class SendLogin:SendMessageBase<UserInfo,RoleInfo>{    public SendLogin():base("登录")    {    }}

其中UserInfo和RoleInfo类分别是存储用户信息、和角色信息


以下我在Packet.cs中自定义了两个数据包

SelfClientPacket,    SelfServerPacket,


修改TNGameClient.cs源码,当客户端接收到来自服务器端的数据包时,将发出相应处理

下载TNGameClient.cs,你将发现我添加了以下几行代码:

目的就是为当户端接收到来自服务器端的数据包时,将发出转发处理

 case Packet.SelfClientPacket:            {                ReceiveMessage.Receive(reader);                break;            }

【服务器】

与客户端类似,先对从客户端发来的数据包解析(Json),接下来转发发送

ServerDateManager.cs

using System;using System.Collections.Generic;using System.Linq;using TNet;using System.IO;using GameDate;using LitJson;public class ServerDateManager{    /// <summary>    /// 解析从客户端发来的数据包    /// </summary>    /// <param name="player"></param>    /// <param name="reader"></param>    public static void ReceiveFunctionFromClient(TcpPlayer player, BinaryReader reader)    {        //解析        string functionName = reader.ReadString();        //开始往客户端发送数据        switch (functionName)        {            case "注册":                UserInfo userinfo = JsonMapper.ToObject<UserInfo>(reader.ReadString());                break;            case "登录":                break;        }    }}/// <summary>/// 回发管理/// </summary>public class Manager{    /// <summary>    ///注册,返回成功    /// </summary>    /// <param name="player">包含客户端里的端口,ip地址信息</param>    /// <param name="userInfo">存储从客户端里发送过来的用户信息</param>    public static void RegistLogic(TcpPlayer player,UserInfo userInfo)    {        //模拟下服务器收到请求响应        Console.WriteLine("账户:" + userInfo.username + ",密码:" + userInfo.password);        {            //在实际项目中,可以向本地服务器中的数据库中提取或存放数据            //例如在注册这里可以将客户端里发来的用户注册信息存储到数据库中        }        //向客户端返回信息        BinaryWriter write = player.BeginSend(Packet.SelfClientPacket);        write.Write("注册");        write.Write(true);        player.EndSend();    }    /// <summary>    /// <summary>    ///注册,返回成功    /// </summary>    /// <param name="player">包含客户端里的端口,ip地址信息</param>    /// <param name="userInfo">存储从客户端里发送过来的用户信息</param>    public static void LoginLogic(TcpPlayer player,UserInfo userInfo)    {        //这里只是模拟下,这里只是简单讲登录后的获得得用户角色信息记录下来        //可以自行修改,比如可以向本地服务器中提取该账号用户信息        RoleInfo roleInfo = new RoleInfo();        roleInfo.date = 1;        roleInfo.name = "即步";        //将类对象转换为json,方便数据发送        string sendStr = JsonMapper.ToJson(roleInfo);        //想客户端发送数据        BinaryWriter write = player.BeginSend(Packet.SelfClientPacket);        write.Write("登录");        write.Write(sendStr);        player.EndSend();    }}

当然,也和客户端类似,当接收识别到客户端发来的数据包时,接而解析转发相应信息回客户端

case Packet.SelfServerPacket:            {               ServerDateManager.ReceiveFunctionFromClient(player,reader);                break;            }



客户端与服务器端准备完成后,接下来测试下

在unity(客户端)中创建一个空对象,添加如下图两个脚本组件,目的与服务器端发生连接


接下来添加一个自定义名为text.cs的C#脚本组件(向服务器端发生SelfServerPacket数据包):

using UnityEngine;using System.Collections;using GameDate;public class Test : MonoBehaviour {// Use this for initializationvoid Start ()    {    }    bool isSend = false;    void Update()    {        if (!isSend)        {            if (TNManager.isConnected)            {                #region 注册                //实例化命令类                SendRegisred regisred = new SendRegisred();                //构造一个数据                UserInfo info = new UserInfo();                info.username = "abcd";                info.password = "123456";                regisred.Send(info, result =>                {                    if (result)                    {                        Debug.Log("注册成功了。");                    }                });                #endregion                #region 登陆                SendLogin login = new SendLogin();                login.Send(info, result =>                {                    Debug.Log("登陆成功,返回信息中:Role ID = " + result.date.ToString() + ", Role Name = " + result.name);                });                #endregion                isSend = !isSend;            }        }    }}


之后在unity控制台窗口中会发现如下图数据,表明客户端与服务器发生了数据交互




0 0
原创粉丝点击