`
ijavagos
  • 浏览: 1199602 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux下如何清空socket的接收缓冲区的数据

阅读更多

最近碰到一个问题,对于阻塞模式的socket通讯,如果要实现设备的命令控制,那么进入命令流前,缓冲区不能存有上次通讯没有取回的信息,否则一旦命令发出,然后读取缓冲区,很显然会读到上一次的剩余数据。做法当然很简单,就是先清除接收区的缓冲数据,可是如何清除?

网上有很多这样的问题,但都没什么规范的解决办法,有的甚至为了达到清空的目的,建议先close一下socket,这个太大手笔了,为了解决一个小问题而大动干戈,根本不是个合理的解决办法。

还有就是用recv读取,但是由于不知道缓存里有多少数据,如果是阻塞模式,到最后必然等到超时才知道数据已经读取完毕,这是个问题。

另一个是用fgetc,通过返回判断是否是feof:

whlie (1) {
a=fgetc(f);
if (feof(f)) break;
//…
b=fgetc(f);
if (feof(f)) break;
//…
}

当然,我不知道读取完毕后最后一次调用fgetc会不会堵塞,需要测试。

在非阻塞模式下,我们用recv就可以轻松搞定了,但是阻塞模式下,由于我们不知道缓冲区有多少数据,不能直接调用recv尝试清除。

使用一个小小的技巧,利用select函数,我们可以轻松搞定这个问题:

select函数用于监视一个文件描述符集合,如果集合中的描述符没有变化,则一直阻塞在这里,直到超时时间到达;在超时时间内,一旦某个描述符触 发了你所关心的事件,select立即返回,通过检索文件描述符集合处理相应事件;select函数出错则返回小于零的值,如果有事件触发,则返回触发事 件的描述符个数;如果超时,返回0,即没有数据可读。

重点在于:我们可以用select的超时特性,将超时时间设置为0,通过检测select的返回值,就可以判断缓冲是否被清空。通过这个技巧,使一个阻塞的socket成了‘非阻塞’socket。

现在就可以得出解决方案了:使用select函数来监视要清空的socket描述符,并把超时时间设置为0,每次读取一个字节然后丢弃(或者按照业务需要进行处理,随你便了),一旦select返回0,说明缓冲区没数据了(“超时”了)。

struct timeval tmOut;      
tmOut.tv_sec = 0;
tmOut.tv_usec = 0;
fd_set         fds;
FD_ZEROS(&fds);
FD_SET(skt, &fds);

int            nRet;

char tmp[2];

memset(tmp, 0, sizeof(tmp));

while(1)
{           nRet= select(FD_SETSIZE, &fds, NULL, NULL, &tmOut);
           if(nRet== 0)  break;
           recv(skt, tmp, 1,0);
}

 这种方式的好处是,不再需要用recv、recvfrom等阻塞函数直接去读取,而是使用select,利用其超时特性检测缓冲区是否为空来判断是否有数据,有数据时才调用recv进行清除。

有人说同样可以用recv和socket的超时设置去清空啊,这个没错,但是你需要直接对socket描述符设置超时时间,而为了清空数据而直接修改socket描述符的属性,可能会影响到其他地方的使用,造成系统奇奇怪怪的问题,所以,不推荐使用。

0
2
分享到:
评论

相关推荐

    Linux网络编程socket错误码分析[参考].pdf

    如果 recv 返回值小于请求的长度时,说明缓冲区已经没有可读数据,但再读不一定会触发 EAGAIN,可能返回 0,表明 TCP 连接已被关闭。 EPIPE EPIPE 错误码的值为 ???,表示 socket 关闭,但是 socket 号并没有置 -1...

    大文件socket通讯传输

    基于linux下的c/c++...【3】客户端两个线程,一个线程负责接收文件进入缓冲区,另一个线程负责写文件数据。 【4】服务器端,命令行./Server_NBuffer 要传输的文件名 【5】客户端,命令行./Client_NBuffer 服务器地址

    Socket 编程.pdf

    而 UDP SOCKET 只有一个接收缓冲区,无流量控制,当接收的数据报溢出时就会被丢弃。 三、 通信域(地址族) 套接字存在于特定的通信域(地址族)中,只有隶属于同一地址族的套接字才能建立对话。Linux 支持 AF_...

    实验三Socket通信实验报告.doc

    //定义从远程计算机接收到数据存放的数据缓冲区 int i = skSocket.ReceiveFrom ( byStream , ref tempRemoteEP ) ; //接收数据,并存放到定义的缓冲区中 string sMessage = System.Text.Encoding.UTF8.GetString ( ...

    基于Linux的Socket网络编程的性能优化

    利用TCP socket禁用Nagle算法实现了最小化报文传输的延时,提高了Socket的性能。...提出了为Bandwidth Delay Product调节TCP窗口,修改socket的发送和接收缓冲区的大小,完全利用可用的带宽。达到较好的网络传输效果。

    基于Linux下IEC61850的研究.pdf

    其中sk_buff含义为套接字缓冲区,定义在/include/linux/skbuff.h中。 5. 数据包发送和接收 要从协议层向设备发送数据,需要使用dev_queue_xmit函数。这个函数对数据进行排队,并交由底层设备驱动程序发送数据包。...

    Linux编程--Linux内核

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

    Linux编程从入门到精通

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

    基于Linux的嵌入式PPP实现.pdf

    Skbuff结构是在各网络协议层和网络设备之间传输数据的缓冲区。Sock结构保存有关BSD Sockets协议特定的信息。Device结构定义了一个网络设备。整个结构中,Socket系统调用实现了Sockets的建立和管理,数据的发送和接收...

    LINUX编程白皮书 (全集)

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

    linux编程白皮书

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

    Linux内核 内容很全

    网络 92 8.1 TCP/IP网络概述 92 8.2 Linux中的TCP/IP网络层次结构 95 8.3 BSD套接字接口 96 8.4 INET的套接字层 97 8.4.1 创建BSD套接字 98 8.4.2 为INET BSD Socket绑定地址 99 8.4.3 建立...

    xenomai与普通linux进程之间通信——XDDP(nRT->RT).docx

    最后,我们需要使用recv函数将数据从套接字中接收,并将其存储到缓冲区中。 在这篇文章中,我们讨论了Xenomai与普通Linux进程之间的通信,包括如何使用XDDP协议实现数据交换。我们也讨论了非实时进程如何将数据发送...

    linux内核源代码情景分析

    2.10 内核缓冲区的管理 2.11 外部设备存储空间的地址映射 2.12 系统调用brk() 2.13 系统调用mmap() 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的...

    LINUX编程白皮书

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

    Linux内核源代码情景分析 (上下册 高清非扫描 )

    2.10 内核缓冲区的管理 2.11 外部设备存储空间的地址映射 2.12 系统调用brk() 2.13 系统调用mmap() 第3章 中断、异常和系统调用 3.1 X86 CPU对中断的硬件支持 3.2 中断向量表IDT的初始化 3.3 中断请求队列的...

    Linux编程白皮书

    2.8.1 减少缓冲区和页缓存大小 25 2.8.2 换出System V共享内存页 26 2.8.3 换出和淘汰页 27 2.9 交换缓存 27 2.10 页换入 28 第3章 进程 29 3.1 Linux进程 29 3.2 标识符 31 3.3 调度 32 3.4 文件 34 3.5 虚拟内存 ...

Global site tag (gtag.js) - Google Analytics