Unity使用webSocket与服务器通信(二)——C#服务器端使用Fleck时的简单服用方法
创始人
2024-05-31 06:22:48
0

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

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

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

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

//用户连入服务器时...
Action OnOpen { get; set; }//用户与服务器断开连接时...
Action OnClose { get; set; }//收到字符串消息时...
Action OnMessage { get; set; }//收到二进制数据时...
Action OnBinary { get; set; }//收到别人发来的ping信息时...
Action OnPing { get; set; }//收到别人发来的pong信息时...
Action OnPong { get; set; }//出错的时候调用...[?谁出错,服务器出错还是连接出错,出的是什么错?]
Action 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:8181server.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 Cookies { get; }IDictionary 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 = 1048576await 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
{/// /// 用户ID/// public string userID;/// /// socket对象/// public IWebSocketConnection socket;/// /// 状态:true-可用状态  false-断开状态/// 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)

相关内容

热门资讯

武陵山天空被鸟群刷屏 转自:JSTV荔枝视频 【#武陵山天空被鸟群刷屏#】眼下...
河南鹤壁有人下河摸金摸铜钱?当... 近日,有网民发布视频称,位于河南省鹤壁市浚县新镇镇卫河流域,有人下河摸金摸铜钱,引发关注。视频显示,...
大连西山水库出现成群黑色大鱼,... 来源:半岛晨报 5月6日下午,市民王先生在大连西山水库发现一群体型较大、通体黝黑的无鳞怪鱼,经专家鉴...
助力工业精神传承,培养创新型人... 5月10日,记者从柳州市教育局获悉,为了更好地将工匠精神、实业报国融入思想政治教育,柳州将打造大中小...
牌桌上的美丽绽放——欧碧奴美容... 转自:衡水日报2025年5月9日,成都青白江东方欲晓十五里休闲中心,160位欧碧奴会员姐姐与亲友闺蜜...
婚姻登记“全国通办”政策问答 来源:“中国民政”微信公号5月10日,新修订的《婚姻登记条例》正式施行,婚姻登记实现“全国通办”。为...
强对流天气致墙体倒塌 3人死亡... 来源:国家应急广播 近日广西百色有网友称参加葬礼时遭遇强对流天气墙体倒塌致多人死伤相关话题冲上社交平...
珍酒李渡举行2024年度股东周... 5月9日,珍酒李渡集团2024年度股东周年大会暨投资者交流会在湖南长沙1912珍酒美食研究所举行,股...
全国仅12个入选!梧州六堡茶国... 转自:梧州发布日前,国家知识产权局公布第一批国家地理标志保护示范区典型案例,全国仅12个保护示范区入...
美业全新动态:杭州美莱受邀出席... 转自:蚌埠新闻网2025年5月7日,杭州美莱受邀亮相2025中国时尚美学盛典Moly Gala,以"...
青年与城市如何共成长?50人论... 来源:中国新闻网 中新网上海5月10日电 题:青年与城市如何共成长?50人论坛交出“上海答卷”作者 ...
葬礼上再发惨剧!3人确认死亡,... 近日,广西百色网友称,参加葬礼遇强对流天气,墙体倒塌致多人死伤。韦女士接受记者采访时表示,近日与家人...
国海证券原总裁意外离世!年61... (转自:金融街1号狙击手)5月10日,据券商中国报道,国海证券原总裁齐国旗近日因遭遇交通意外,不幸离...
永达股份:子公司部分产品应用于... 永达股份(001239)5月9日在业绩说明会上表示,公司控股子公司江苏金源高端装备有限公司部分产品应...
永远不能忘却的纪念(今日谈) 来源:人民日报80年前的伟大胜利打败了不可一世的法西斯势力,带给世人恒久的启迪:光明必将驱散黑暗,正...
社工“寻味儿”救场避免险情   本报讯(实习记者侯国棣)近日,平谷区滨河街道南小区社区84岁的李大爷忘记了厨房正在煮饭的锅,把锅...
美元贬值,这次不一样 美国总统特朗普经常说希望美元贬值。在他看来,这可以降低制造业出口成本,从而促进出口,帮助减少美国巨额...
张本智和:深受雨果世界杯夺冠冲... 来源:九派新闻 近日,日本乒乓球队举行多哈世乒赛赛前新闻发布会,日本男乒选手张本智和在接受采访时谈到...
具茨山原来是中华文明的C位 【#具茨山原来是中华文明的C位#】具茨山位于黄帝故里河南新郑西南,属中岳嵩山东南余脉,东西延绵约40...
李姓股民向ST东时发起索赔 刘...   受损股民可至Hehson股民维权平台登记该公司维权:http://wq.finance.sina...