网络-阻塞IO模型

1.阻塞IO

最常见、效率低、不耗费cpu

阻塞I/O 模式是最普遍使用的I/O 模式,大部分程序使用的都是阻塞模式的I/O 。

缺省情况下(及系统默认状态),套接字建立后所处于的模式就是阻塞I/O 模式。

学习的读写函数在调用过程中会发生阻塞相关函数如下:

•读操作中的read、recv、recvfrom

读阻塞--》需要读缓冲区中有数据可读,读阻塞解除

•写操作中的write、send

写阻塞--》阻塞情况比较少,主要发生在写入的缓冲区的大小小于要写入的数据量的情况下,写操作不进行任何拷贝工作,将发生阻塞,一旦缓冲区有足够的空间,内核将唤醒进程,将数据从用户缓冲区拷贝到相应的发送数据缓冲区。

注意:sendto没有写阻塞

1)无sendto函数的原因:

sendto不是阻塞函数,本身udp通信不是面向链接的,udp无发送缓冲区,即sendto没有发送缓冲区,send是有发送缓存区的,即sendto不是阻塞函数。

2)UDP不用等待确认,没有实际的发送缓冲区,所以UDP协议中不存在缓冲区满的情况,在UDP套接字上进行写操作永远不会阻塞。

2.丢包、粘包、拆包

tcp不会造成丢包,udp不会造成粘包和拆包

UDP通信没有发送缓存区, 它不保证数据的可靠性。因此,UDP通信是将数据尽快发送出去,不关心数据是否到达目标主机. 但是UDP有接收缓存区, 因为数据发送过快, 如果接收缓存区内数据已满, 继续发送数据, 可能会出现丢包。

丢包出现原因: 接收缓存区满 网络拥堵, 传输错误

相比之下,TCP是一种面向连接的传输协议,它需要保证数据的可靠性和顺序性。TCP有发送缓存区和接收缓存区, 如果发送频率过快, 且内容小于发送缓存区的大小 , 可能会导致多个数据的粘包。如果发送的数据大于发送缓存区, 可能会导致拆包。

UDP是基于数据报文发送的,每次发送的数据包,在UDP的头部都会有固定的长度, 所以应用层能很好的将UDP的每个数据包分隔开, 不会造成粘包。

TCP是基于字节流的, 每次发送的数据报,在TCP的头部没有固定的长度限制,也就是没有边界,那么很容易在传输数据时,把多个数据包当作一个数据报去发送,成为了粘包,或者传输数据时, 要发送的数据大于发送缓存区的大小,或者要发送的数据大于最大报文长度, 就会拆包;

TCP不会丢包,因为TCP一旦丢包,将会重新发送数据包。(超时/错误重传)

TCP粘包、拆包发生原因:

发生TCP粘包或拆包有很多原因,常见的几点:

1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包

2、待发送数据大于MSS(传输层的最大报文长度),将进行拆包(到网络层拆包 - id ipflags )。

3、要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包

4、接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包

粘包解决办法:

解决问题的关键在于如何给每个数据包添加边界信息,常用的方法有如下:

1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2、发送端将每个数据包封装为固定长度,这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

4、延时发送

 

 拆包

粘包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值