socket缓冲区以及阻塞模式

原创 2016年06月02日 07:53:24
在《socket数据的接收和发送》一节中讲到,可以使用 write()/send() 函数发送数据,使用 read()/recv() 函数接收数据,本节就来看看数据是如何传递的。

socket缓冲区

每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。

write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。

TCP协议独立于 write()/send() 函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。

read()/recv() 函数也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。

图:TCP套接字的I/O缓冲区示意图

这些I/O缓冲区特性可整理如下:
  • I/O缓冲区在每个TCP套接字中单独存在;
  • I/O缓冲区在创建套接字时自动生成;
  • 即使关闭套接字也会继续传送输出缓冲区中遗留的数据;
  • 关闭套接字将丢失输入缓冲区中的数据。

输入输出缓冲区的默认大小一般都是 8K,可以通过 getsockopt() 函数获取:
  1. unsigned optVal;
  2. int optLen = sizeof(int);
  3. getsockopt(servSock, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen);
  4. printf("Buffer length: %d\n", optVal);
运行结果:
Buffer length: 8192
这里仅给出示例,后面会详细讲解。

阻塞模式

对于TCP套接字(默认情况下),当使用 write()/send() 发送数据时:
1) 首先会检查缓冲区,如果缓冲区的可用空间长度小于要发送的数据,那么 write()/send() 会被阻塞(暂停执行),直到缓冲区中的数据被发送到目标机器,腾出足够的空间,才唤醒 write()/send() 函数继续写入数据。

2) 如果TCP协议正在向网络发送数据,那么输出缓冲区会被锁定,不允许写入,write()/send() 也会被阻塞,直到数据发送完毕缓冲区解锁,write()/send() 才会被唤醒。

3) 如果要写入的数据大于缓冲区的最大长度,那么将分批写入。

4) 直到所有数据被写入缓冲区 write()/send() 才能返回。

当使用 read()/recv() 读取数据时:
1) 首先会检查缓冲区,如果缓冲区中有数据,那么就读取,否则函数会被阻塞,直到网络上有数据到来。

2) 如果要读取的数据长度小于缓冲区中的数据长度,那么就不能一次性将缓冲区中的所有数据读出,剩余数据将不断积压,直到有 read()/recv() 函数再次读取。

3) 直到读取到数据后 read()/recv() 函数才会返回,否则就一直被阻塞。

这就是TCP套接字的阻塞模式。所谓阻塞,就是上一步动作没有完成,下一步动作将暂停,直到上一步动作完成后才能继续,以保持同步性。
TCP套接字默认情况下是阻塞模式,也是最常用的。当然你也可以更改为非阻塞模式,后续我们会讲解。
版权声明:本文为芝麻软件工作室原创文章,未经芝麻软件工作室允许不得转载。

socket的发送和接收缓冲区

对于每一个TCP的SOCKET来说,都有一个发送缓冲区和接受缓冲区与之对应,下面举个例子说说发送缓冲区、接受缓冲区、滑动窗口协议之间的关系。 一、recv端     在监听套接字上准备...
  • H002399
  • H002399
  • 2015年06月23日 14:52
  • 3362

socket中用户自定义缓冲区的原因及方式

我们在使用TCP/IP编程的时候除了socket有收发数据缓冲区之外,通常我们还要自己定一个数据的收发缓冲区: 1,为什么系统已经有收发缓冲区了,我们还要自定义收发缓冲区呢?      a...
  • farmwang
  • farmwang
  • 2017年03月21日 17:42
  • 1256

设置SOCKET的发送与接收缓冲区

设置SOCKET的发送与接收缓冲区
  • wesleyluo
  • wesleyluo
  • 2011年01月18日 10:55
  • 41327

网络(4):socket中用户自定义缓冲区的原因及方式

我们在使用TCP/IP编程的时候除了socket有收发数据缓冲区之外,通常我们还要自己定一个数据的收发缓冲区: 1,为什么系统已经有收发缓冲区了,我们还要自定义收发缓冲区呢?      a.假设应...
  • wentianyao
  • wentianyao
  • 2016年09月03日 00:54
  • 1186

send和recv只是内核缓冲区和应用程序缓冲区之间的搬运工---严格来讲send和recv并不具备发送和接收功能

谈到网络socket编程, 我们不得不提两个基本也很重要的函数:send和recv.  对socket编程理解不深的童鞋容易产生这样一个错误的认识: send函数是用来发送数据, 而recv函数是用来...
  • stpeace
  • stpeace
  • 2015年02月11日 22:07
  • 6120

socket粘包,socket缓冲区设

这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下:  一 .两个简单概念长连接与短连接: 1.长连接     Clie...
  • yqj234
  • yqj234
  • 2016年06月21日 19:09
  • 1036

如何获取SOCKET 发送缓冲区使用大小

问题描述:socket编程,发送少量数据时,send/write等发送函数会立即返回成功,发送的数据会存在TCP发送缓冲区中,依靠TCP协议栈自身的重传机制来保证该数据 被接收端收到;我们的问题是 发...
  • lyx___vvv
  • lyx___vvv
  • 2016年12月01日 16:24
  • 2891

socket缓冲区大小 .

http://blog.csdn.net/jfkidear/article/details/7826789   socket缓冲区大小默认为64 k 理论上最优大小为 带宽乘以往返时间(RTT通...
  • yangruibao
  • yangruibao
  • 2012年11月08日 09:59
  • 2896

关于socket读写缓冲区小结

关于socket的发送缓冲区网上有诸多的讨论,这里个人小结一下,希望对以后有些帮助。首先,看下面一段代码, //设定socket参数 #define dfUdpRcvCacheSize  256*...
  • jiangyiaxiu
  • jiangyiaxiu
  • 2011年11月08日 13:15
  • 3119

socket缓冲区的影响

       TCP套接字的可用rcvBuf的大小就是TCP通告另一端的窗口大小(滑动窗口),由TCP的流量限制措施决定rcvBuf不会溢出;而UDP套接字rcvBuf没有流量限制,因此发送的数据报大...
  • wqf363
  • wqf363
  • 2006年11月02日 20:32
  • 2043
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:socket缓冲区以及阻塞模式
举报原因:
原因补充:

(最多只允许输入30个字)