EAGAIN错误

linux/unix下读写socket时可能发生EAGAIN错误,比如在非阻塞(non-block)的情况下,客户端给服务器发送了一个空字符,事件接收到消息连接会让服务器会去读,但是没有数据可读,会发生错误:

EAGAIN : Resource temporarily unavailable

因为是异步的立马返回了,又没有读到数据所以会提示EAGAIN,提示当前不可读稍后重试。其它的比如文件操作或者fork失败等也会产生该错误。
windows上,EAGAIN的名字叫做EWOULDBLOCK,在使用非阻塞套接字进行异步编程时,需要通过errno对这些情况作出处理

各层传输长度约束

MTU,最大传输单元,链路层的最大长度,通常为1500字节
IP包,包头中以16位数来描述其长度,最大为65535字节
当IP包大小超过了MTU值,就需要进行分片,然后在客户端进行重组。但不同网络的MTU值可能不同,会导致数据包被再次分片。若将IP包设置为不允许分片(分片会降低性能),当某一网络的MTU值比发送时的MTU值要小,则数据包将被丢弃,发送方会收到ICMP消息,通知其需要进行分片。这个最小的MTU称为路径MTU

MSS,最大分段大小,表示TCP传往另一端的最大数据的长度,其值越大,一次传输的数据越多。
MSS = MTU - IP头长度 - TCP头长度, 通常为1460 = 1500 - 20 - 20。
建立TCP连接的两端在三次握手时会协商MSS的大小,一方发出syn报文时会带上mss大小,另一方应答时也是如此。双方会选择较小的mss作为发送tcp分片的大小。

socket缓冲区

默认大小为1024*8 = 8096个字节,默认是socket先将数据发送到系统缓冲区,也就是8096bytes的地方,之后接收函数再从系统缓冲区拷贝数据到socket缓冲区,发送出去。若经常很快将缓冲区写满,可以将缓冲区的设置大一些,使用setsockopt函数
使用缓冲区设置的目的是减少网络IO,这点很重要。不用缓冲区,数据立即发送,网络忙的时候更易出错。

缓冲区的拷贝,send时也称为应用缓冲区拷贝到发送缓冲区,新拷贝到发送缓冲区的数据会由系统来发送,注意并不是立刻就由系统发送了,系统会自行处理,可近似看作立即发送。发送缓冲区中的数据,发送后在得到对端ack响应前不会删除。

Nagle算法

默认情况下,数据发送使用Nagle算法,其要求在任何时刻最多只能有一个未被确认的数据块
Nagle算法的规则:

  1. 如果包长度达到MSS,则允许发送

  2. 如果该包含有FIN,则允许发送

  3. 设置了TCP_NODELAY选项,则允许发送

  4. 未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送

  5. 上述条件都未满足,但发生了超时(一般为200ms),则立即发送

算法的上的很明确,避免向网络中发送过多的小包,先行等待200ms左右,如果上一个包的ACK仍然没有收到或是包长度仍然未达到MSS才继续发包,这样可以提高网络吞吐量,但降低了实时性,可以通过设置TCP_NODELAY来禁用Nagle算法


quietin
761 声望44 粉丝

兴趣在程序语言, 高性能, 分布式等方面