unity客户端使用HP-SOCKET连接服务器(客户端与服务器端“状态更新”的模型与实现之二)

在C# WINFORM 项目中使用HP-SOCKET网络引擎(客户端与服务器端“状态更新”的模型与实现之一)

Unity2D 客户端使用HP-SOCKET连接服务器(客户端与服务器端“状态更新”的模型与实现之二)

服务器端的对象更新(客户端与服务器端“状态更新”的模型与实现之三)

HP-SOCKET的服务器已经启动,我们在WINFORM用HP-SOCKET client组件去连接:

1、使用了HP-SOCKET的client组件。

2、使用的PACK包模式,就是只接收整包的数据,不用再担心粘包掉包之类的。

3、发送的是:一个对象封包为json字符串再转为的一串byte。

            bwobj one = new bwobj { bwtype = 1, longjson = "123456789123456789" };
            var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(one));         
            HPclient.Send(bytes, bytes.Length);

4、服务器接收到的一串byte,解包为json字符串,再解为一个对象。

这些收到的对象被放在一个线程安全的ConcurrentBag对象集合里面,后面会安排其它线程来去走这些报文对象。

            //data->string->object 解包
            bwobj one = JsonConvert.DeserializeObject<bwobj>(Encoding.UTF8.GetString(data));        
            bws.Add(one);

client端的winform全部实现代码:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

using HPSocket;
using HPSocket.Tcp;
using HPSocket.Thread;
using Newtonsoft.Json;

namespace client2020
{
    public partial class Form1 : Form
    {

        private readonly ITcpPackClient HPclient = new TcpPackClient();

        public static ConcurrentBag<bwobj> bws = new ConcurrentBag<bwobj>(); //报文集合   

        public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 演示设置client属性
            // 缓冲区大小
            HPclient.SocketBufferSize = 4096; // 4K
            // 异步连接
            HPclient.Async = true;

            // pack模型专有设置
            HPclient.MaxPackSize = 4096;     // 最大封包
            HPclient.PackHeaderFlag = 0x01;  // 包头标识, 要与客户端对应, 否则无法通信


            // 要连接的服务器地址和端口(也可以调用Connect()方法时传入服务器ip和端口)
            // 例如: _client.Connect("127.0.0.1", 555)
            HPclient.Address = "127.0.0.1";
            HPclient.Port = 15555;

            // 事件绑定
            HPclient.OnPrepareConnect += OnPrepareConnect;
            HPclient.OnConnect += OnConnect;
            HPclient.OnReceive += OnReceive;
            HPclient.OnClose += OnClose;
        }



        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            client_go();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {            
            //线程           
            Thread lsThread = new Thread(new ThreadStart(sendsomething));
            lsThread.IsBackground = true;
            lsThread.Start();           
        }

        private void sendsomething()
        {
            bwobj one = new bwobj { bwtype = 1, longjson = "123456789123456789" };
            var bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(one));         
            HPclient.Send(bytes, bytes.Length);
        }


        private void client_go()
        {
            try
            {            
                // 连接到目标服务器
                if (!HPclient.Connect())
                {
                    throw new Exception($"error code: {HPclient.ErrorCode}, error message: {HPclient.ErrorMessage}");
                }    
            }
            catch (Exception ex)
            {
                AddLog($"exception: {ex.Message}");
            }
        }

        private HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
        {
            AddLog($"OnPrepareConnect({sender.Address}:{sender.Port}), socket handle: {socket}, hp-socket version: {sender.Version}");
            return HandleResult.Ok;
        }

 
        private HandleResult OnConnect(IClient sender)
        {
            AddLog("OnConnect()");
            return HandleResult.Ok;
        }


        private HandleResult OnReceive(IClient sender, byte[] data)
        {
            AddLog($"OnReceive(), data length: {data.Length}"); 
            return HandleResult.Ok;
        }


        private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
        {
            AddLog($"OnClose(), socket operation: {socketOperation}, error code: {errorCode}");
            return HandleResult.Ok;
        }


        private void AddLog(string log)
        {
            listBox1.Items.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {log}\r\n");
        }


        public class bwobj
        {
            public int bwtype { get; set; }
            public string longjson { get; set; }
        }

    }
}

--------------unity客户端连接HP-SOCKET服务器-----------------------

后面测试“状态更新”的例子,可能会用到2D图像的展示,比如客户端控制一个小坦克对象,所以unity也要连上服务器。

unity2019中建一个项目,加入canvas桌布,加入一个button,canvas桌布和主摄像机关联,在game中设定屏幕分辨率。

button中新建一个脚本NewBehaviourScript.cs。

全部代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Collections.Concurrent;
using System.Text;

using HPSocket;
using HPSocket.Tcp;
using HPSocket.Thread;
using Newtonsoft.Json;

public class NewBehaviourScript : MonoBehaviour
{
    private readonly ITcpPackClient HPclient = new TcpPackClient();
    // Start is called before the first frame update
    void Start()
    {
        // 缓冲区大小
        HPclient.SocketBufferSize = 4096; // 4K
                                          // 异步连接
        HPclient.Async = true;

        // pack模型专有设置
        HPclient.MaxPackSize = 4096;     // 最大封包
        HPclient.PackHeaderFlag = 0x01;  // 包头标识, 要与客户端对应, 否则无法通信

        // 要连接的服务器地址和端口(也可以调用Connect()方法时传入服务器ip和端口)
        // 例如: _client.Connect("127.0.0.1", 555)
        HPclient.Address = "127.0.0.1";
        HPclient.Port = 15555;

        // 事件绑定
        //  HPclient.OnPrepareConnect += OnPrepareConnect;
        HPclient.OnConnect += OnConnect;
        HPclient.OnReceive += OnReceive;
        HPclient.OnClose += OnClose;

        HPclient.Connect();
    }

    // Update is called once per frame
    void Update()

    {  //按下ESC键则退出游戏 
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            HPclient.Dispose();
            Application.Quit();
        }
    }
    public void sendsomething()
    {
        bwobj one = new bwobj { bwtype = 1, longjson = "longlonglonglong" };
        var bytes = System.Text.Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(one)); 
        HPclient.Send(bytes, bytes.Length);
    }
    
    private HandleResult OnPrepareConnect(IClient sender, IntPtr socket)
    {
        AddLog($"OnPrepareConnect({sender.Address}:{sender.Port}), socket handle: {socket}, hp-socket version: {sender.Version}");
        return HandleResult.Ok;
    }
    

    private HandleResult OnConnect(IClient sender)
    {
        AddLog("OnConnect()");
        return HandleResult.Ok;
    }


    private HandleResult OnReceive(IClient sender, byte[] data)
    {
        AddLog($"OnReceive(), data length: {data.Length}");
        return HandleResult.Ok;
    }


    private HandleResult OnClose(IClient sender, SocketOperation socketOperation, int errorCode)
    {
        AddLog($"OnClose(), socket operation: {socketOperation}, error code: {errorCode}");
        return HandleResult.Ok;
    }

    private void AddLog(string log)
    {
        Debug.Log($"{log}\r\n");
    }

    public class bwobj
    {
        public int bwtype { get; set; }
        public string longjson { get; set; }
    }

}

注意点:

1、在assets目录中放入hpsocket和json的类库:

2、程序编译发布选择对应环境为x86_64模式:

unity客户端使用HP-SOCKET连接了服务器:

unity hpsocket json dll文件打包共享:

https://pan.baidu.com/s/1kX7qixyJ-wXbb65L5yK5ww

发布了249 篇原创文章 · 获赞 85 · 访问量 49万+

猜你喜欢

转载自blog.csdn.net/ot512csdn/article/details/104011213