问几个有关 NIO 的问题

2021-04-25 14:23:29 +08:00
 Joker123456789

本人对 NIO 的理解程度有限,网上的资料又不够详细,很多东西都搜不到,所以在此问问各位大神,如果兴趣的话还望指教。 谢谢啦。

客户端发起一个 http 请求到服务端

  1. 此时 selector 会把 read 状态的 channel 给获取到 并进入迭代, 这个 channel 里包含本次请求的所有报文吗? 注意是本次请求。

  2. 会不会因为网络原因或者其他常见原因 导致数据有断层,比如客户端发送了 1234,但是 channel 里是 12 34.从而导致读 channel 的时候在断层处 返回 0,而导致读取停止?

分片传输

假如有这样一个 http 报文

POST /demo HTTP/1.1
content-type:application/json
content-length:1000

12345678910qwertyuioasdfghjkl

我以分两片为例子。

分片传输是将报文分为这样的两份( A )?

第一片

POST /demo HTTP/1.1
content-type:application/json
content-length:50

12345678910qwer


第二片
POST /demo HTTP/1.1
content-type:application/json
content-length:50

tyuioasdfghjkl

还是这样的两份( B )?

第一片

POST /demo HTTP/1.1
content-type:application/json
content-length:100

12345678910

第二片
qwertyuioasdfghjkl

如果是 B 的分法,那么 NIO 在收到第二片之后,丢给协议层,这个数据里没有任何特征,协议层是怎么判断出这个报文属于什么协议,从而给对应的协议解析器来进行解析的呢?

NIO 有没有什么高效的办法来 判断本次请求的协议类型,除了分析报文里的特征

我现在是根据报文里的特征来分析的,感觉不太对劲。

3723 次点击
所在节点    Java
24 条回复
cqsc
2021-04-25 21:30:18 +08:00
TCP 协议是面向字节流的 同时为了提高效率可能会将多个数据包合并一起发送 或者在接收时多个数据包被拆分成若干小包 这个就需要你自己的在设计应用层协议的时候考虑到如何处理了 确保能够读取到完整的应用层报文
kongch
2021-04-26 10:18:24 +08:00
先从概念看:tcp 是流,属于传输层; http 是应用层,所以答案肯定是 B 。
再用反证法:如果用 A 的模式,你看看你猜测的两个包传输了多少重复内容,计算机先驱们不会有这么低级的错误。
再通过实践:用 wireshark 抓个包就能知道肯定不会是 A 了。
4kingRAS
2021-04-26 17:30:56 +08:00
协议层不会分“包”的,netty 会设置 delimiter,比如\r\n 。 每次你发的“包”会按照\r\n 来分,所以即使这个请求没有一起到达也没事。
Chinsung
2021-04-27 09:35:05 +08:00
Netty 中有一个 Http 消息聚合 handler,HttpObjectAggregator,作用就是将过长的 post 请求在多包多次到达的情况将一个长 http 请求聚合成一个完整的请求。
不只是 NIO,其实你这种场景在 BIO 也会出现,本质上是协议解析的问题,网络在发送请求的时候,对于客户端读取方,不论是 BIO 还是 NIO,在 read 的时候都会出现单次 read 只 read 到了一部分报文。
C 里面这种写法会更多,大部分协议或者自定义协议,都一定要有报文头标识和报文结束标识,一般是找几个字节的不可见字符这种,然后自己搞个缓冲区,取出一段一段报文去处理。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/773105

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX