Sockets 非阻塞tun/tap文件描述符上的read()获取EAGAIN错误
我想从非阻塞tun/tap文件描述符读取IP数据包Sockets 非阻塞tun/tap文件描述符上的read()获取EAGAIN错误,sockets,file-descriptor,openvpn,tun,Sockets,File Descriptor,Openvpn,Tun,我想从非阻塞tun/tap文件描述符读取IP数据包tunfd 我将tunfd设置为非阻塞,并在libevent中为其注册一个READ_EV事件 当事件被触发时,我首先读取前20个字节以获取IP头,然后 读剩下的 nr_bytes = read(tunfd, buf, 20); ... ip_len = .... // here I get the IP length .... nr_bytes = read(tunfd, buf+20, ip_len-20); 但是对于读取(tunfd,buf
tunfd
我将tunfd
设置为非阻塞,并在libevent中为其注册一个READ_EV事件
当事件被触发时,我首先读取前20个字节以获取IP头,然后
读剩下的
nr_bytes = read(tunfd, buf, 20);
...
ip_len = .... // here I get the IP length
....
nr_bytes = read(tunfd, buf+20, ip_len-20);
但是对于读取(tunfd,buf+20,ip_len-20)
我犯了一个错误,实际上应该有一个完整的包,
所以应该有一些字节,
为什么我会犯这样的错误
tunfd与非阻塞模式或libevent不兼容
谢谢 使用TUN/TAP进行读写,就像在数据报套接字上进行读写一样,必须针对完整的数据包。如果读入的缓冲区太小,无法容纳完整的数据包,缓冲区将被填满,数据包的其余部分将被丢弃。对于写入,如果您写入部分数据包,驱动程序将认为它是完整的数据包,并通过隧道设备发送截断的数据包
因此,当您读取TUN/TAP设备时,必须提供至少与
TUN
或TAP
界面上配置的MTU一样大的缓冲区。您的意思是,每次read()只能返回正好1个数据包?不是多个包?此外,如果我太频繁地向tun fd写入数据,并且没有足够的缓冲区,会发生什么?例如,如果只有200字节的缓冲区,但我想写一个500字节的数据包。将写入200个字节还是500个字节都不写入?谢谢是,read()
一次只能返回1个(完整)数据包。如果write()
太多,那么write()
可能最终会被阻止,但它仍然只会写入完整的数据包。write()会被阻止吗?如果套接字是非阻塞的,它不是返回一个EAGAIN错误吗?哦,是的,当然。如果您处于非阻塞模式,它将返回EAGAIN
,而不是阻塞。这是正确的,@SimonLanghoff。使用缓冲读写器的原因之一是批量处理更多数据并减少read()
/write()
/recv()
/send()
系统调用的数量。但对于TUN/TAP,一个系统调用=一个数据包是接口的要求,因此您无法进行优化。