LINUX socket SIOCOUTQ获取发送队列信息

在某C/S结构程序测试时发现一个问题

当无线网络拥塞的时候,无线层丢包很严重,TCP socket可能需要若干秒(worst case n>5)才能发出去。

发送方调用write(fd)将报文发送的时候实际上只是写入了内核的write buffer。接收方什么时候能收到报文是个未知数。

在某些需要同步状态机的地方,发送方最好能够确认接收方收到报文后再进行下一步动作。

C: How to tell the status of a socket
by George Michael|Published 30 October 2011
If you are trying to check if a socket is empty but you cannot use select(), because what you need is to check the write buffers instead of the read ones just to be sure that you have successfully managed to send all data to your peers before terminating, or if you want to tell if a socket buffer is full.

You can use the ioctl to find out.

To check a write buffer if it empty (assuming you have already put data there and want to check if they were consumed):

ioctl(fd, SIOCOUTQ, &pending);
Where fd is the socket’s file descriptor and pending the variable were the remaining size of data will be returned.

To check a read buffer if it empty (assuming someone has already put data there and you want to check if they there is any without consuming them):

ioctl(fd, SIOCINQ, &pending);
*note the difference on the second parameter, where we change the flag from SIOCOUTQ to SIOCINQ
Among other includes be sure to add these:

#include <sys/ioctl.h>
#include <linux/sockios.h>

linux提供了ioctl(fd, SIOCOUTQ, &count)方法来查询一个tcp socket的write buffer是否清空。发送方一般可以用这个方法来判断对端是否收到报文。

调试程序的时候遇到了一个奇怪的问题。

CLIENT端实际上已经收到了SERVER发送的报文,开始进行下一步动作。 但是SERVER端的out queue始终显示没有发送完毕。

经过Debug后发现,实际上是client端收到报文后发送给server的TCP ACK在空口中丢失。尽管client端已经接收完毕数据,但是由于server端没有收到对应的ack,导致server端一直认为发送端没有收到数据。


所以发送方可以通过SIOCOUTQ来辅助判断tcp socket的状态。但是最好还是不要用SIOCOUTQ来绑定程序逻辑。不然容易造成死锁。



阅读更多
文章标签: linux
上一篇杀掉所有用户进程,保留当前进程: killall5
下一篇一个诡异的tcp连接异常问题
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭