七层
应用进程
粘包问题以及如何理解是 TCP 面向字节流协议?
之所以会说 TCP 是面向字节流的协议,UDP 是面向报文的协议,是因为操作系统对 TCP 和 UDP 协议的发送方的机制不同,也就是问题原因在发送方。
先来说说为什么 UDP 是面向报文的协议?
当用户消息通过 UDP 协议传输时,操作系统不会对消息进行拆分,每个 UDP 报文就是一个用户消息的边界,这样接收方在接收到 UDP 报文后,读一个 UDP 报文就能读取到完整的用户消息。由于UDP有消息保护边界,不会发生粘包拆包问题
你可能会问,如果收到了两个 UDP 报文,操作系统是怎么区分开的?
操作系统在收到 UDP 报文后,会将其插入到队列里,队列里的每一个元素就是一个 UDP 报文,这样当用户调用 recvfrom() 系统调用读数据的时候,就会从队列里取出一个数据,然后从内核里拷贝给用户缓冲区。
再来说说为什么 TCP 是面向字节流的协议?
当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。
这时,接收方的程序如果不知道发送方发送的消息的长度,也就是不知道消息的边界时,是无法读出一个有效的用户消息的,因为用户消息被拆分成多个 TCP 报文后,并不能像 UDP 那样,一个 UDP 报文就能代表一个完整的用户消息。
因此,我们不能认为一个用户消息对应一个 TCP 报文,正因为这样,所以 TCP 是面向字节流的协议。
------
tcp是基于字节流传输的,使用tcp协议传输的数据是无边界的。。。
解决方法:
固定包大小(浪费空间),
设置标志位:
我们可以在两个用户消息之间插入一个特殊的字符串,这样接收方在接收数据时,读到了这个特殊字符,就把认为已经读完一个完整的消息。
自定义消息结构:
我们可以自定义一个消息结构,由包头和数据组成,其中包头包是固定大小的,而且包头里有一个字段来说明紧随其后的数据有多大。
getpost
使用场景上
- 在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;
- Get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;
时间消耗上:
Get和Post还有一个重大区别:
Get产生一个TCP数据包;Post产生两个TCP数据包。
对于Get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据),而对于Post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
比如说:Get只需要汽车跑一趟就把货送到了,而Post得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。由于Post需要两步,时间上消耗的要多一点,所以Get比Post更有效率。
http缓存