前面专栏实现了WebSocket
的握手和消息收发:WebSocket专栏
现在我们从后台到前端,实现一个简单的聊天室,实现效果:用户登录
、发送消息
、接收消息
、用户离开
。
大部分逻辑是基于Text消息类型,将具体的消息封装成JSON
字符串在客户端和服务器间传送。
0、消息封装
所有消息基于JSON,基本结构如下:
{
"action": "消息类型",
"payload": {}
}
payload里面封装具体的消息内容,下面就是最基本的几个消息封装。
1、用户登录
客户端发送消息
{
"action": "login",
"payload": {"name": "用户名称"}
}
服务端响应给客户端
{
"action": "login",
"payload": {"connectionId": 100000}
}
然后广播给其他用户,告诉他们有客户进入聊天室
{
"action": "login",
"payload": {"name": "用户名称", "connectionId": 100000}
}
2、发送消息
客户端发送消息
{
"action": "post",
"payload": {"message": "消息内容"}
}
服务端将消息广播给所有用户。
{
"action": "post",
"payload": {"message": "消息内容", "connectionId": 100000, "name": "用户名称"}
}
3、用户主动离开
客户端发送消息,payload没有内容
{
"action": "quit",
"payload": {}
}
服务端将用户离开的消息广播给所有用户。
{
"action": "exit",
"payload": {"connectionId": 100000, "name": "用户名称"}
}
https://github.com/hooow-does-it-work/websocket-chat/tree/main/Chat/Payloads
这里可以找到这些消息的C#封装,程序用了反射,借助Attribute
实现消息的自动解析和封装。
1、Messager封装
我们封装一个消息处理器,实现上面介绍的消息收发。
https://github.com/hooow-does-it-work/websocket-chat/blob/main/Chat/Connection.cs
同时实现一个ConnectionGroup
对用户进行分组,当前示例用到的只有ConnectionGroup
内部定义的默认分组:Default
。
我们着重关心Text类型的消息,消息的广播都是在分组内实现。
/// <summary>
/// 收到文本消息
/// </summary>
/// <param name="payload"></param>
protected override void OnText(string payload)
{
IPayload payload_ = Payload.Parse(payload);
if (payload_ == null) return;
//登录
if (payload_ is Login login)
{
_name = login.name;
_group = ConnectionGroup.Default;
//先回复自己
Send(new Payloads.Response.Login() {
connectionId = _connectionId
});
//然后广播给分组内的所有人
_group.Enter(this);
return;
}
//发布
if (payload_ is Post post)
{
//广播给分组内的所有人
_group.Broadcast(new Payloads.Response.Post()
{
connectionId = _connectionId,
message = post.message,
name = _name
});
return;
}
//主动退出
if (payload_ is Quit)
{
Close();
return;
}
}
2、总结
后端代码不多,主要是实现消息的解析和封装以及广播。
写的都是最简单的逻辑,没有深层次的封装。:
1、广播用循环;
2、消息发送使用队列保证准确投放;
下一篇简单介绍下前端的代码。