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缓冲区以及阻塞模式的更多相关文章

  1. socket缓冲区以及阻塞模式(七)

    一.socket缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区. 以下用write()/send()表示写数据/发送数据,read()/recv() 表示读数据/接收 ...

  2. 基于C++简单Windows API的socket编程(阻塞模式)

    1. 概述:简单的基于Windows API的socket点对点聊天程序,为了方便初学者,本文代码均采用阻塞原理编写. 2. 代码样例 Server.cpp(服务端) #include <cst ...

  3. Python socket(TCP阻塞模式)基础程式

    前置知识:Python基础语法,socket库 tips: 1. 默认HOST_IP:127.0.0.1 2. 默认HOST_PORT:7676 参考代码: 1. 客户端程式 #!/usr/bin/e ...

  4. socket异步通信-如何设置成非阻塞模式、非阻塞模式下判断connect成功(失败)、判断recv/recvfrom成功(失败)、判断send/sendto

    socket异步通信-如何设置成非阻塞模式.非阻塞模式下判断connect成功(失败).判断recv/recvfrom成功(失败).判断send/sendto 博客分类: Linux Socket s ...

  5. 看到关于socket非阻塞模式设置方式记录一下。

    关于socket的阻塞与非阻塞模式以及它们之间的优缺点,这已经没什么可言的:我打个很简单的比方,如果你调用socket send函数时: 如果是阻塞模式下: send先比较待发送数据的长度len和套接 ...

  6. Socket阻塞模式和非阻塞模式的区别

    简单点说: 阻塞就是干不完不准回来,    非组赛就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系 ...

  7. Python Socket单线程+阻塞模式

    Python之旅]第五篇(二):Python Socket单线程+阻塞模式 python Socket单线程 Socket阻塞模式 串行发送 摘要:  前面第五篇(一)中的一个Socket例子其实就是 ...

  8. 服务器编程心得(四)—— 如何将socket设置为非阻塞模式

    1. windows平台上无论利用socket()函数还是WSASocket()函数创建的socket都是阻塞模式的: SOCKET WSAAPI socket( _In_ int af, _In_ ...

  9. UE4 Socket多线程非阻塞通信

    转自:https://blog.csdn.net/lunweiwangxi3/article/details/50468593 ue4自带的Fsocket用起来依旧不是那么的顺手,感觉超出了我的理解范 ...

随机推荐

  1. P2733 家的范围 Home on the Range

    又是一校内模拟赛见的题 不知道为什么出题人怎么这么喜欢USACO的Farmer John的他的牛... 感觉这道题不是特别的难,但也不很水 同机房的神仙们都说这个题是一道二维前缀和的裸题,但我当时的确 ...

  2. wpf 查找 子元素

    RightContainer.ApplyTemplate();//如果找不到,就执行该句试一试 var xxx=UIHelper.FindChild<ScrollViewer>(Right ...

  3. matlab转python

    最近在做把matlab代码转成python代码,没有用过matlab,python也只是局限于爬虫,所以.... matlab与python最大的不同是,matlab的下标是从1开始的,python和 ...

  4. celery在Django中的集成使用

    继上回安装和使用Redis之后,看看如何在Django中使用Celery.Celery是Python开发分布式任务列队的处理库.可以异步分布式地异步处理任务,也可定时执行任务等等.通常我们可以在Dja ...

  5. win7下docker环境搭建nginx+php-fpm+easyswoole开发环境

    基础的环境已在文章nginx.php-fpm.swoole HTTP/TCP压测对比中搭建了,现在是在这个基础上在搭建easyswoole开发环境 主要要修改的地方是dnmp包里面的docker-co ...

  6. Vue.js中 watch 的高级用法

    假设有如下代码: <div> <p>FullName: {{fullName}}</p> <p>FirstName: <input type=&q ...

  7. Ionic入门三:列表

    列表是一个应用广泛的界面元素,在所有移动app中几乎都会使用到. 列表可以是基本文字.按钮,开关,图标和缩略图等. 列表项可以是任何的HTML元素.容器元素需要list类,每个列表项需要使用item类 ...

  8. 基于Laravel开发博客应用系列 —— 使用Bower+Gulp集成前端资源

    本节我们将讨论如何将前端资源集成到项目中,包括前端资源的发布和引入.本项目将使用 Bower 和 Gulp 下载和集成jQuery.Bootstrap.Font Awesome 以及 DataTabl ...

  9. Maven项目使用阿里云的Maven库

    Maven项目下载一些jar包非常慢,有时候一个项目能下一个上午,因此可以考虑使用阿里云的Maven库,因为是国内的,所以下载速度非常酷 单个项目使用阿里云的Maven库: pom文件中 <!- ...

  10. STP协议树配置

    STP协议树作用 为了提高网络可靠性,交换网络中通常会使用冗余链路. 然而,冗余链路会给交换网络带来环路风险 并导致广播风暴以及MAC地址表不稳定等问题进而会影响到用户的通信质量. 生成树协议STP( ...