Unity使用webSocket与服务器通信(二)——C#服务器端使用Fleck时的简单服用方法

news2024/11/17 2:57:13

C#服务端用到Fleck包,它包含哪些可用的回调函数,有哪些常用的api方法?

演示:服务端收到Unity用户发来的信息
请添加图片描述

1、Fleck服务器提供哪些回调函数

Fleck提供的回调函数有下面几种:

//用户连入服务器时...
Action OnOpen { get; set; }

//用户与服务器断开连接时...
Action OnClose { get; set; }

//收到字符串消息时...
Action<string> OnMessage { get; set; }

//收到二进制数据时...
Action<byte[]> OnBinary { get; set; }

//收到别人发来的ping信息时...
Action<byte[]> OnPing { get; set; }

//收到别人发来的pong信息时...
Action<byte[]> OnPong { get; set; }

//出错的时候调用...[?谁出错,服务器出错还是连接出错,出的是什么错?]
Action<Exception> OnError { get; set; }

2 、服务器提供的其它API

其它常用的api主要有:

//发送字符串
Task Send(string message);

//发送字节码(二进制数据)
// 1Byte = 8 bits
// 1KB = 1024 Bytes
// 1MB = 1024KB
Task Send(byte[] message);

//发送一个ping信息
Task SendPing(byte[] message);

//发送一个pong信息
Task SendPong(byte[] message);

//关闭连接
void Close();

//关闭连接?关闭连接池中指定序号的连接?
void Close(int code);
  • ping pong的作用是啥?
    WebSocket为了保持客户端、服务端的实时双向通信,需要确保客户端、服务端之间的TCP通道保持连接没有断开。然而,对于长时间没有数据往来的连接,如果依旧长时间保持着,可能会浪费包括的连接资源。但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接。这个时候,可以采用心跳来实现。
    发送方->接收方:ping;
    接收方->发送方:pong;

C# 在WinForm里使用Fleck作为服务器的简单示例代码:

 private void button1_Click(object sender, EventArgs e)
{
    if (hasStartedServer)//不重复启动服务器实例
        return;

    var server = new WebSocketServer("ws://192.168.0.137:8081");  //ws://localhost:8081    ws://127.0.0.0:8181
    server.Start(socket =>
    {
        //连上时...
        socket.OnOpen = () =>
        {
            Debug.WriteLine($"有新用户连入:{socket.ConnectionInfo.ClientIpAddress}");
        };

        //断开时...
        socket.OnClose = () =>
        {
            Debug.WriteLine($"用户断开连接:{socket.ConnectionInfo.ClientIpAddress}");
            UserSockets.First(x => x.socket.ConnectionInfo.Id == socket.ConnectionInfo.Id).connected = false;
        };

        //收到string信息时...
        socket.OnMessage = message =>
        {
            socket.Send($"服务器收到消息 : {DateTime.Now.ToString()}");
            Debug.WriteLine($"收到一条消息,来自:{socket.ConnectionInfo.ClientIpAddress}");
            Debug.WriteLine(message);

            var cmd  = message.Split("#")[0];
            if (cmd == "name")
            {
                var userID = message.Split("#")[1];
                Debug.WriteLine($"收到一条消息,来自用户:{userID}  连接id:{socket.ConnectionInfo.Id}");

                UserSocket user = new UserSocket(){userID = userID,socket = socket,connected = true};
                UserSockets.Add(user);
            }
        };

        //收到二进制信息时...
        socket.OnBinary = bytes =>
        {
            var userName = UserSockets.First(x => x.socket.ConnectionInfo.Id == socket.ConnectionInfo.Id)
                .userID;
            Debug.WriteLine($"收到二进制数据,长度为{bytes.Length}Bytes,来自ip:{socket.ConnectionInfo.ClientIpAddress},userID ={userName}");
        };
    });

    Debug.WriteLine("服务器已经启动!");
    hasStartedServer = true;
}

3、服务器与客户端建立的连接包含哪些信息

  public interface IWebSocketConnectionInfo
  {
    string SubProtocol { get; }

    string Origin { get; }

    string Host { get; }

    string Path { get; }

    string ClientIpAddress { get; }

    int ClientPort { get; }

    IDictionary<string, string> Cookies { get; }

    IDictionary<string, string> Headers { get; }

    Guid Id { get; }

    string NegotiatedSubProtocol { get; }
  }

每次建立的连接,Id号是唯一的。

4、服务器接收数据时是否会粘包?

经测试,同一连接连续向服务器发送数据时,每次OnBinary收到的消息是完整的。
还没瞻仰源码,后面有空看看,server端TCP接收数据时,应该是做了包的合并处理,接到一个整坨数据,才调用的OnBinary。
在这里插入图片描述

请添加图片描述

  • Unity用户端代码
    连发50笔数据,每次发送1M bytes
 int i = 0;
 while (i < 50)  //连发50笔数据,每次发送1M bytes
 {
     var bytesArray = new byte[1048576];  // 1024 * 1024 = 1048576
     await websocket.Send(bytesArray);    //或者直接await,测试结果一样
     Debug.Log($"发送数据-{i}");
     i++;
 }
  • C#服务端代码
    每当收到数据时,把收到的数据长度打印出来
socket.OnBinary = bytes =>
   {
        Debug.WriteLine($"收到二进制数据,长度为{bytes.Length}Bytes,来自{socket.ConnectionInfo.ClientIpAddress}");
   };

5、同一个ip上有两个应用同时发来信息,如何区分这些连接属于哪个用户?

简要思路:每个用户端启动的时候,需要用户名登录,建立连接时,告诉服务器这个socket是哪个userID的,凡是该用户建立连接,后台都把该连接绑定到user ID。

  • 1、每次建立连接,connection的id是唯一的
    在这里插入图片描述

  • 2、服务器端维护一个【连接列表】:(string userID - > webSocket sockt),如下所示:

public class UserSocket
{
    /// <summary>
    /// 用户ID
    /// </summary>
    public string userID;

    /// <summary>
    /// socket对象
    /// </summary>
    public IWebSocketConnection socket;

    /// <summary>
    /// 状态:true-可用状态  false-断开状态
    /// </summary>
    public bool connected;
}
userIDsocketconnected
guestsocket1true
user1socket2true
user2socket3false
userNsocketMtrue

客户端建立连接的时候,发送信息给服务器,告诉服务器该连接对应那个用户名。
服务器收到信息后,及时更新【连接列表】。

  • 用户端在建立连接的时候,发送一个string命令,告诉服务器这个连接后面是哪个用户(user ID)
websocket.OnOpen += () =>
{
    Debug.Log("连接成功!!");   
    websocket.SendText($"name#user001"); //发送用户id
};
  • 服务器收到信息的处理
 //收到二进制信息
socket.OnBinary = bytes =>
{
    var userName = UserSockets.First(x => x.socket.ConnectionInfo.Id == socket.ConnectionInfo.Id)
        .userID;
    Debug.WriteLine($"收到二进制数据,长度为{bytes.Length}Bytes,来自ip:{socket.ConnectionInfo.ClientIpAddress},userID ={userName}");
};

收到信息,且识别了是哪个userID发来的
请添加图片描述

6、本文测试环境

Win10 + Unity2021.3.18 + VS2019(.NET 5.0)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398974.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在Windows 10中安装PostgreSQL 15

PostgreSQL是一个强大的开源对象关系数据库系统,经过35年的积极开发,在可靠性、功能健壮性和性能方面赢得了很高的声誉。 通过官方文档可以找到大量的信息来描述如何安装和使用PostgreSQL。开源社区为熟悉PostgreSQL、发现它的工作原理和寻找职业机会提供了许多有用的地方。…

APP违法违规收集使用个人信息合规评流程和范围

近期&#xff0c;工信部通报2023年第1批《侵害用户权益行为的APP通报》&#xff08;总第27批&#xff09;&#xff0c;共通报46款APP&#xff08;SDK&#xff09;&#xff0c;这些被责令限期整改的APP&#xff08;SDK&#xff09;&#xff0c;涉及的问题主要包括3个方面&#x…

Easy Deep Learning——卷积层

为什么需要卷积层&#xff0c;深度学习中的卷积是什么&#xff1f; 在介绍卷积之前&#xff0c;先引入一个场景 假设您在草地上漫步&#xff0c;手里拿着一个尺子&#xff0c;想要测量草地上某些物体的大小&#xff0c;比如一片叶子。但是叶子的形状各异&#xff0c;并且草地非…

【Unity3D小技巧】Unity3D中判断Animation以及Animator动画播放结束,以及动画播放结束之后执行函数

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在日常开发中&#xff0c;可能会遇到要判断Animation或者Anima…

MySQL workbench数据表和数据结构

数据表和数据结构的关系 数据表 学号姓名位置26002351李晓丽126002589张明伟226003214李雪冬326002132汪涵426006541邱明罕526003654李丽6 怎样去描述上面的数据表&#xff0c;用【数据表结构】表示 表头字段名字段类型位数备注学号xuehao整数/字符8 姓名xingming字符4 座…

煤矿人员精确定位解决方案,维护作业人员生命安全

近日&#xff0c;应急管理部党委书记、部长王祥喜主持召开全国安全防范工作视频会议。会议强调&#xff0c;要深刻吸取内蒙古露天煤矿坍塌等重特大事故教训&#xff0c;举一反三全面排查整治重点行业领域重大安全隐患&#xff0c;坚决遏制重特大事故&#xff0c;切实维护人民群…

【数据结构·考研】后序线索二叉树

之前我们介绍了中序线索二叉树的构造、遍历、寻找前趋和寻找后继&#xff1b;先序线索二叉树的构造、遍历、寻找后继。先序线索二叉树无法解决寻找前趋的任务&#xff0c;中序线索二叉树既可以寻找前趋结点也可以寻找后继结点。 今天我们再来看一下后序线索二叉树的构造&#…

apt-get通过代理更新系统

apt-get通过代理更新系统1. 源由2. 需求3. 分析4. 步骤4.1 安装CCProxy4.2 配置CCProxy4.3 apt-get更新4.4 apt-get升级4.5 apt-get安装5. 补充资料 命令行设置代理6. 参考资料1. 源由 apt-get经典操作就是通过网络与服务器通信&#xff0c;下载相应的包来安装和更新软件。 这…

docker容器内安装gcc(trunk 最新版本)以及LLVM

1、docker内部只有wget以及git命令 项目需要&#xff0c;得更新docker容器中的gcc和LLVM版本但是由于没有预先安装apt、apt-get以及yum&#xff0c;导致很多安装过程就是鸡生蛋蛋生鸡反应。暂时没有找到合适的解决的方法&#xff0c;如果有大佬知道的话&#xff0c;欢迎留言哈…

ZeroTier实现内网穿透详细教程,无需公网IP,实现异地组网

ZeroTier实现内网穿透详细教程&#xff0c;无需公网IP&#xff0c;实现异地组网ZeroTier1.官网注册账号&#xff0c;创建自己的局域网段2.点击创建好的网络&#xff0c;进入设置界面进行设置3.下载客户端&#xff0c;安装客户端&#xff0c;然后连接到网络中4.加入网络成功后&a…

pocsuite3安装及使用

pocsuite3安装及使用简介项目地址环境配置及安装环境要求安装&#xff08;详情可以参考[https://pocsuite.org/](https://pocsuite.org/)&#xff09;使用方法运行模块加载目标参数&#xff1a;Console模式查看有哪些模块使用Telnet 弱密码模块这里以flask模板注入漏洞为例pocs…

阿里云短信验证

1.了解阿里云用户权限操作 需要通过个人账户获得 授权码&#xff08;id、密码&#xff09;&#xff0c;再通过这些信息获得服务 阿里云网址 &#xff1a;https://www.aliyun.com/ 1.登陆阿里云服务器2.进入个人账号然后点击 AccessKey 管理3.创建用户组4.添加用户组权限&…

SYSU程设c++(第三周) 对象类、类的成员、类与结构体的区别、类的静态成员

对象&类 类用于指定对象的形式&#xff0c;它包含数据的表示方法和用于处理数据的方法。 • 类中的数据和方法称为类的成员。 • 函数在一个类中也被称为类的成员。 定义一个类&#xff0c;其效果是定义一个数据类型的蓝图。它定义了类的对象包括了什么&#xff0c;以及可…

C++基础了解-08-C++运算符

C运算符 一、C 运算符 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符&#xff0c;并提供了以下类型的运算符&#xff1a; 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 杂项运算符 二、算术运算符 下表显示了 C 支持的算术运算符…

led灯性价比最高的是哪款?2023最新的哪种led灯质量比较好

Led作为一种固态半导体&#xff0c;具有自发光、高可控性的特点&#xff0c;高效节能&#xff0c;省电环保&#xff0c;并且根据材料的不同&#xff0c;发出的光线颜色也不同&#xff0c;因此广泛用于各种照明灯具&#xff0c;台灯也不例外。 作为一种适合工作学习或者工作休闲…

跑步耳机入耳好还是不入耳好、十大跑步运动耳机品牌排行榜推荐

健身房经常会播放一些节奏较快的歌曲&#xff0c;这样能够激发大家在运动过程中的动力&#xff0c;所以运动时聆听音乐确实比较有效果&#xff0c;居家运动、室外跑步时选择运动耳机就变成了刚需&#xff0c;首先不能影响其他人、佩戴时要稳定&#xff0c;音质和续航要有保证&a…

npm install 原理

npm基本使用node.jsNode.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。在任何地方安装了node&#xff0c;那么就可以运行JavaScript。所以在服务器上就可以运行js了。js就全栈了。node安装的同时就安装了npm。直接去官网下载&#xff0c;双击安装即可。安装完毕之后…

java基于springboot仓库管理系统的设计与实现

项目介绍 基于 SpringBoot 的仓库管理系统拥有多种角色&#xff0c;可供用户自定义使用。 功能模块 一、业务模块 1、客户管理 2、供应商管理 3、商品管理 4、商品进货管理 5、商品退货管理 6、商品销售管理 7、商品销售退货管理 二、系统模块 菜单管理&#xff0c;角色管…

Java高级工程师特别熟悉的js基础 | 面向对象编程/原型链/继承

面向对象编程/原型链/继承 面向对象编程 什么是面向对象编程&#xff1f; 面向对象是⼀种编程思想&#xff0c;经常被拿来和⾯面向过程⽐比较。其实说的简单点&#xff0c;面向过程关注的重点是动词&#xff0c;是分析出解决问题需要的步骤&#xff0c;然后编写函数实现每个步…

WIFI标签操作步骤

1. 打开并设置手机WIFI热点&#xff0c;设置SSID为ESL&#xff0c;密码为123456789&#xff08;如下图&#xff09; ​ 2. 运行APP&#xff0c;设置要接入的WIFI名称密码等信息&#xff08;如下图&#xff09; ​ 3. 长按背面按键&#xff08;长按2-3秒&#xff09;&#xff0c…