`
ijavagos
  • 浏览: 1189623 次
  • 性别: 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
分享到:
评论

相关推荐

    大文件socket通讯传输

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

    实验三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编程--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内核源代码情景分析 (上下册 高清非扫描 )

    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.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 建立...

    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.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 内核源代码分析

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

    zero-copy-socket-test

    在我的 4 核 8 线程 3.5Ghz i7-3770K 上测试 ASIO 最大化 UDP 发送... Linux 在 65507 下使用 2 个线程和 1 个缓冲区达到 6881 Mb/秒。 Windows 最大速度为 3000 Mb/秒,带有 2 个线程和 4 个缓冲区 @ 65507。 真正的

Global site tag (gtag.js) - Google Analytics