上一篇我已经实现了聊天室,并且在协议中实现了4种类型的消息传输。其实还可以添加videoaudiolive等等类型。

不过假如把目前的协议看作RCP1.0版的话,这个版本就只支持有限的4种消息。精力有限啊。也许RCP2.0就可以把videoaudio类型加进去?

这不是这篇番外考虑的。而是我在定义和实现协议的过程中注意到了一些问题。

系统的网络缓冲区是怎么回事?

因为我自己定义了一个400字节的buffer用来接收消息。如果接收到的消息超出了400字节,WebSocket会给出提示,将EndOfMessage字段设置为false。

这到底是

  • 客户端暂停了本次发送,等到服务器再一次执行ReceiveAsync方法时才继续发送?
  • 还是WebSocket对象本身内置了缓冲区?消息全部都暂存在缓冲区?

我使用浏览器开发者工具监视了ws消息发送过程,结合后台断点调试,发现WebSocket采用了第二种方案。把消息全部存在缓冲区,我用buffer读一次,就取出来一点。

既然是缓冲区,那么一个WebSocket对象的内置缓冲区有多大?客户端发送的文件长度超过了WebSocket对象的内置缓冲区的大小时怎么办?

看看websocket协议怎么说

看起来websocket 协议中数据长度上限为 2^127,可以认为没有限制。因而在实际使用中 websocket 消息长度限制只取决于服务器实现。

System.Net.WebSockets.WebSocket对象内部一定使用了一个MemoryStream之类的东西来暂存数据。

问题是那为什么他不直接把那个缓冲区给我?我还要自己再去创建一个缓冲区,从他的缓冲区读数据?我不太清楚。

多个WebSocket与http服务器怎么共用一个端口?

典型的socket监听{IP:Port}

但是我在websocket中没有看到这些信息。

如果你的 Web API 服务器在端口 80 上运行,那么 WebSocket 连接也会使用端口 80 来传输数据

比较疑惑的是,操作系统接收到一个TCP数据包,怎么知道交给http服务器,还是哪个websocket连接?

原来一个TCP端口可以建立多个TCP连接,只要(服务器IP:服务器Port:客户端IP:客户端Port)唯一就行。

看看调试

TCP连接 服务器IP 服务器Port 客户端IP 客户端Port 连接Id
游客_1 ::1 5234 ::1 54008 0HN3PID8UHKHN
游客_2 ::1 5234 ::1 54481 0HN3PID8UHKHO
游客_3 ::1 5234 ::1 54556 0HN3PID8UHKHP

操作系统就是根据这个表决定把从端口接收的数据发往哪个游客线程。

看看实际连接是怎么样的?

手动管理连接看看?

由于websockt我们看不到客户端发起连接,服务端接收连接的过程,我自己用socket测试一下。

代码非常简单

  • 服务器监听端口
  • 等待客户端连接,然后维护到一个集合中
  • 每接到连接,就开启一个聊天线程
    static void Main(string[] args)
{
//服务器
if (args.Length == 1) {
int serverPort = Convert.ToInt32(args[0]);
var server = new TcpListener(IPAddress.Parse("127.0.0.1"),serverPort);
Console.WriteLine($"TCP服务器 127.0.0.1:{serverPort}");
server.Start();
int cnt = 0;
Task.Run(async() =>
{
List<TcpClient> clients= new List<TcpClient>();
while (true)
{
TcpClient client = await server.AcceptTcpClientAsync();
clients.Add(client);
cnt++;
var ep = client.Client.RemoteEndPoint as IPEndPoint;
Console.WriteLine($"TCP客户端_{cnt} {ep.Address}:{ep.Port}");
//给这个客户端开一个聊天线程
//操作系统将会根据游客端口对应表将控制权交给对应游客线程
StartChat(client);
}
}).Wait();
}
//客户端
else if (args.Length == 3)
{
int clientPort = Convert.ToInt32(args[0]);
int serverPort = Convert.ToInt32(args[1]);
string msg = args[2];
var client=new TcpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), clientPort));
Console.WriteLine($"TCP客户端 127.0.0.1:{clientPort}");
Task.Run(async () =>
{
await client.ConnectAsync(new IPEndPoint(IPAddress.Parse("127.0.0.1"), serverPort));
Console.WriteLine($"连接到 127.0.0.1:{serverPort}");
//打招呼
var msgBytes=UTF8Encoding.UTF8.GetBytes(msg);
await client.Client.SendAsync(msgBytes);
//等待数据,阻塞在这里,保持连接
await client.Client.ReceiveAsync(new ArraySegment<byte>(new byte[100]));
}).Wait();
}
} public static async Task StartChat(TcpClient client)
{
var buffer = new byte[100];
while (true)
{
//阻塞接收消息
int msgLength = await client.Client.ReceiveAsync(new ArraySegment<byte>(buffer));
string str=UTF8Encoding.UTF8.GetString(buffer,0,msgLength);
Console.WriteLine(str);
}
}
}

我们测试建立一个服务端,和三个连接到这个服务端的客户端

虽然三个游客都向一个服务器端口5234发送消息,但操作系统根据端口连接对应表知道将消息发送给哪个线程。就好像在一个端口划分出来了3个信道。

  • 每个信道可以使用具体的http协议或我们写的RCP协议来序列化和反序列化
  • 要注意的是,这些不同的连接(TcpClient)是同一个TCPLisener对象到的。这就是在一个程序中使用多种通信协议。

基于webapi的websocket聊天室(番外一)的更多相关文章

  1. 基于springboot的websocket聊天室

    WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...

  2. 使用.NET Core和Vue搭建WebSocket聊天室

    博客地址是:https://qinyuanpei.github.io.  WebSocket是HTML5标准中的一部分,从Socket这个字眼我们就可以知道,这是一种网络通信协议.WebSocket是 ...

  3. 基于flask的网页聊天室(四)

    基于flask的网页聊天室(四) 前言 接前天的内容,今天完成了消息的处理 具体内容 上次使用了flask_login做用户登录,但是直接访问login_requare装饰的函数会报401错误,这里可 ...

  4. 基于flask的网页聊天室(一)

    基于flask的网页聊天室(一) 基本目标 基于flask实现的web聊天室,具有基本的登录注册,多人发送消息,接受消息 扩展目标 除基本目标外添加当前在线人数,消息回复,markdown支持,历史消 ...

  5. websocket聊天室

    目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...

  6. WebSocket聊天室demo

    根据Socket异步聊天室修改成WebSocket聊天室 WebSocket特别的地方是 握手和消息内容的编码.解码(添加了ServerHelper协助处理) ServerHelper: using ...

  7. Netty入门(一)之webSocket聊天室

    一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...

  8. 基于flask的网页聊天室(三)

    基于flask的网页聊天室(三) 前言 继续上一次的内容,今天完成了csrf防御的添加,用户头像的存储以及用户的登录状态 具体内容 首先是添加csrf的防御,为整个app添加防御: from flas ...

  9. 基于flask的网页聊天室(二)

    基于flask的网页聊天室(二) 前言 接上一次的内容继续完善,今天完成的内容不是很多,只是简单的用户注册登录,内容具体如下 具体内容 这次要加入与数据哭交互的操作,所以首先要建立相关表结构,这里使用 ...

  10. 用Java构建一个简单的WebSocket聊天室

    前言 首先对于一个简单的聊天室,大家应该都有一定的概念了,这里我们省略用户模块的讲解,而是单纯的先说说聊天室的几个功能:自我对话.好友交流.群聊.离线消息等. 今天我们要做的demo就能帮我们做到这一 ...

随机推荐

  1. C#_面试题1

    C#_面试题1 1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么? 答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方 ...

  2. CSS 布局专题

    0x01 浮动布局 (1)常见网页布局 顶部商标栏(Logo):展示网站的标志.名称以及具有代表性的图片 导航栏(Navigation):展示网站大概的分类 左侧边栏(Left-side Bar):展 ...

  3. 重新整理 .net core 实践篇———承载[外篇]

    前言 简单介绍一下承载. 正文 名称叫做承载,其实就是.net core 定义的一套长期运行的服务的规范. 这个服务可以是web服务,也可以是其他服务,比如tcp,或者一些监控服务. 这里以监控服务为 ...

  4. 【Nano Framework ESP32篇】WS2812 彩色灯带实验

    地球人皆知,许多物联网教程作者的心中都深爱着一灯大师,所以第一个例程总喜欢点灯,高级一点的会来个"一闪一闪亮晶晶".老周今天要扯的也是和灯有关的,但不单纯地点个灯,那样实在不好玩, ...

  5. Ajax 原理是什么?如何实现?

    一.是什么 AJAX全称(Asynchronous Javascript And XML) 即异步的JavaScript 和XML,是一种创建交互式网页应用的网页开发技术,可以在不重新加载整个网页的情 ...

  6. k8s架构与原理介绍

    K8s概述 目录 K8s概述 1.什么是K8s 2.K8s 设计架构 3. k8s重要节点描述 4. 过程原理: 5. k8s的核心功能 6. k8s的历史 7. k8s的安装方式 8. k8s的应用 ...

  7. pycharm更换主题,pycharm更换皮肤,pycharm更换不同颜色

    1.首先  点击File→进入setting 2. 在settings里面找到appearance 3.选择 Theme,下拉即可修改 4.选择不同的主题,darcula是黑色,其他两个是白色

  8. 使用Docker搭建MongoDB 5.0版本副本集集群

    1.mongodb集群 首先我们需要了解mongodb的集群模式,mongodb安装分为单机安装和集群安装.集群安装分为:主从复制(Master-Slaver)集群.副本集(Replica Set)集 ...

  9. Serverless Kubernetes 落地实践

    ​简介:如何通过原生 Kubernetes 提供 Serverless 能力?如何借力丰富的云原生社区生态?本文将给大家介绍一下我们在 Serverless Kubernetes 上的落地实践. 作者 ...

  10. [FAQ] Sortable 拖拽组件, 火狐浏览器中打开新窗口问题

      Q:用了 sortable 组件,在火狐浏览器中进行拖拽时,会打开新窗口 ? Sortable组件地址,https://github.com/SortableJS/Sortable 当前处理方式 ...