socket缓冲区以及阻塞模式详解
在《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() 函数获取:
- unsigned optVal;
- int optLen = sizeof(int);
- getsockopt(servSock, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen);
- 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缓冲区以及阻塞模式详解相关推荐
- socket缓冲区以及阻塞模式
socket缓冲区 每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区. write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从 ...
- delphi Winsock非阻塞模式详解
Winsockt的TClientSocket设置ClientType的属性为ctNonBlocking.则通讯模式为非阻塞模式. ctBlocking为阻塞模式,这里说一下阻塞与非阻塞的一些区别. c ...
- 创建三个并发进程linux,Linux下几种并发服务器的实现模式(详解)
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...
- 1 linux下tcp并发服务器的几种设计的模式套路,Linux下几种并发服务器的实现模式(详解)...
1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...
- Spotify敏捷模式详解三部曲第一篇:研发团队
本文转自:Scrum中文网 引言 2018年4月,来自北欧瑞典的音乐流媒体公司.百亿美元独角兽Spotify创造了历史,它成为了当代上市公司当中,第一家通过"直接上市"的方式在美国 ...
- linux apache两种工作模式详解
apache两种工作模式详解 刚接触这两个配置时很迷糊,全部开启或全部注释没有几多变化.今天搜索到这么一篇讲得还不错的文章,看了几篇,还是不能完全记住,做一个收藏. 空闲子进程:是指没有正在处理请求的 ...
- 转:Java 7 种阻塞队列详解
转自: Java 7 种阻塞队列详解 - 云+社区 - 腾讯云队列(Queue)是一种经常使用的集合.Queue 实际上是实现了一个先进先出(FIFO:First In First Out)的有序表. ...
- 敏捷开发系列学习总结(13)——Spotify敏捷模式详解三部曲第一篇:研发团队
分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!点击浏览教程 引言 2018年4月,来自北欧瑞典的音乐流媒体公司.百亿美元独角兽Spotify创造 ...
- IoC与DI工厂、单例、原型模式详解
1.工厂模式 1.1 工厂模式的由来 在现实生活中我们都知道 原始社会自给自足(没有工厂) 农耕社会有了小作坊(简单工厂,如民间酒坊) 工业革命后有了流水线(工厂方法,自产自销) 现代产业链中有代工厂 ...
最新文章
- ConcurrentHashMap实现原理及源码分析
- TensorFlow 2.0.0-RC0版发布,专注于简单性与易用性
- inxtrackup mysql_雪糕 的动态 - SegmentFault 思否
- SpringBoot AOP完全讲解一:基础概念
- java和asp.net core_.NET Core和ASP.NET Core简介与区别
- Linux ping的原理与实现
- u-boot-2011.06-rc2移植到mini2440开发板(一)
- 推荐系统(2)-协同过滤1-UserCF、ItemCF
- python写抽奖转盘_[宜配屋]听图阁
- android 控件随手指移动_Android 实习生面试经历记录
- C++智能指针的实现与使用(详解)
- EXPLAIN mysql性能调优
- HDU 3790最短路径问题 [最短路最小花费]
- GridView 72般绝技(一)
- Java中类和对象的区别
- 静态图片怎么做成gif图?如何将静态图做成动态图
- memcpy和memset使用时需要区分的注意点
- 涵林同学21浙工大计算机考研心路历程(非正经、无干货)
- c语言字符三维数组定义时赋值,c语言中三维数组的赋值顺序?
- (6)自旋模型基态算法
热门文章
- 构造函数必须是public吗_c++ 构造函数,析构函数必须要给成公有的吗?
- quartus2管教锁定出不来_Quartus II 中常见Warning 原因及解决方法(转载)
- Nginx Mac笔记
- 整型的赋值超出该类型的取值范围
- C. Present(二分 + 扫描线)
- vue中父子组件通信的坑
- 团队开发项目--校园知网 nabcd 需求分析
- 【题解】Luogu P3674 小清新人渣的本愿
- MySql_5-7安装教程
- 5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)