赞
踩
C#服务端用到Fleck包,它包含哪些可用的回调函数,有哪些常用的api方法?
演示:服务端收到Unity用户发来的信息
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; }
其它常用的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);
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; }
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号是唯一的。
经测试,同一连接连续向服务器发送数据时,每次OnBinary收到的消息是完整的。
还没瞻仰源码,后面有空看看,server端TCP接收数据时,应该是做了包的合并处理,接到一个整坨数据,才调用的OnBinary。
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++;
}
socket.OnBinary = bytes =>
{
Debug.WriteLine($"收到二进制数据,长度为{bytes.Length}Bytes,来自{socket.ConnectionInfo.ClientIpAddress}");
};
简要思路:每个用户端启动的时候,需要用户名登录,建立连接时,告诉服务器这个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; }
userID | socket | connected |
---|---|---|
guest | socket1 | true |
user1 | socket2 | true |
user2 | socket3 | false |
… | … | … |
userN | socketM | true |
客户端建立连接的时候,发送信息给服务器,告诉服务器该连接对应那个用户名。
服务器收到信息后,及时更新【连接列表】。
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发来的
Win10 + Unity2021.3.18 + VS2019(.NET 5.0)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。