对于socket发送数据时是否要加锁及write read的阻塞非阻塞
偶尔讨论到了socket发送数据时是否应该加锁的问题,就在网上查了一下,下面是大神陈硕的答案
- 对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避免 contention,可以用 SO_REUSEPORT 来实现这一点。
- 对于 TCP,通常多线程读写同一个 socket 是错误的设计,因为有 short write 的可能。假如你加锁,而又发生 short write,你是不是要一直等到整条消息发送完才解锁(无论阻塞IO还是非阻塞IO)?如果这样,你的临界区长度由对方什么时候接收数据来决定,一个慢的 peer 就把你的程序搞死了。
这里解释下什么是short write
对于一个非阻塞的TCP套接口,如果其发送缓冲区中根本没有空间,输出函数调用将立即返回一个EWOULDBLOCK错误。如果其发送缓冲区中有一些空间,返回值将是内核能够拷贝到该缓冲区中的字节数。这个字节数也称为不足计数(应该就是short write的意思)
那么陈硕大神的意思是 如果接收方的滑动窗口一直为0,则发送方一直不会发送数据,则会一直持有锁,就算是非阻塞的,立刻返回后我们就不对接下来的数据进行发送了么?则一直等待在那里
socket分为阻塞模式和非阻塞模式。
阻塞 | 非阻塞 | |
read | 接收缓冲区只要有数据就立即返回,只有当接收缓冲区为空时才阻塞等待 | 无论有无数据,都立即返回 |
write | 只有发送缓冲区可以放下整个buffer时才返回,否则阻塞 | 无论发送缓冲区是否能放下整个buffer,都立即返回。返回能够放下的字节数 |
1. read总是在接收缓冲区有数据时立即返回,而不是等到给定的read buffer填满时返回。
只有当receive buffer为空时,blocking模式才会等待,而nonblock模式下会立即返回-1(errno = EAGAIN或EWOULDBLOCK)
2. blocking的write只有在缓冲区足以放下整个buffer时才返回(与blocking read并不相同)
nonblock write则是返回能够放下的字节数,之后调用则返回-1(errno = EAGAIN或EWOULDBLOCK)
对于blocking的write有个特例:当write正阻塞等待时对面关闭了socket,则write则会立即将剩余缓冲区填满并返回所写的字节数,再次调用则write失败(connection reset by peer),这正是下个小节要提到的:
对于socket发送数据时是否要加锁及write read的阻塞非阻塞的更多相关文章
- .net 中异步SOCKET发送数据时碰到的内存问题
做CS的开发一直都是这样的方式: server端用 C++编写,采用IOCP机制处理大量客户端连接.数据接收发送的问题 client端用 C++ 或C# 写,没什么特殊要求. 最近工作时间上比较宽裕, ...
- c++ socket发送数据时,sendData = char * string 导致的乱码问题
解决方法:将string 通过copy函数复制到某个char[] 1. string res =“xxx”; char arr[100]; int len = res.copy(arr, 100); ...
- HTTP 请求方式: GET和POST的比较当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。
什么是HTTP? 超文本传输协议(HyperText Transfer Protocol -- HTTP)是一个设计来使客户端和服务器顺利进行通讯的协议. HTTP在客户端和服务器之间以request ...
- 【Debug】串口发送数据时部分字节被拉长,出现帧错误,原因MCU进入低功耗模式导致串口时钟停了!
串口发送数据时部分字节被拉长,出现帧错误,原因MCU进入低功耗模式导致串口时钟停了!
- 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时
在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...
- STM32的USART发送数据时如何使用TXE和TC标志
在USART的发送端有2个寄存器,一个是程序可以看到的USART_DR寄存器,另一个是程序看不到的移位寄存器,对应USART数据发送有两个标志,一个是TXE=发送数据寄存器空,另一个是TC=发送结束. ...
- (原)关于udp的socket发送数据耗时的问题探讨
转载请注明出处:http://www.cnblogs.com/lihaiping/p/6811791.html 本学习笔记,仅用于问题探讨,如有不同,可以讨论. 最近在看流媒体分发服务器的相关代码,其 ...
- 关于form表单或者Ajax向后台发送数据时,数据格式的探究
最近在做一个资产管理系统项目,其中有一个部分是客户端向服务端发送采集到的数据的,服务端是Django写的,客户端需要用rrequests模块模拟发送请求 假设发送的数据是这样的: data = {'s ...
- 测试ajax发送数据时在控制台看不到请求信息
都是因为我把alert(xmlhttp);alert(url);打印测试数据放到了xmlhttp.open("GET",url,true);之前,导致后面的发送请求不执行了!
随机推荐
- git移除文件夹的版本控制
案例背景:git提交的时候把bin文件下的各种.dll提交上去了,然后每次提交都得提交好多文件,很容易忽略你真正修改的东西,故对这些不必要的东西忽略掉 解决方案:git rm 命令参数 具体实施: 1 ...
- Java JDK 配置环境变量
使用了java也有了两年了,安装了很多次jdk都记不住安装步骤 = =,刚刚又配置了一次,码一下步骤: 1.右击"此电脑" ---> "属性" ----& ...
- 在SecureCRT中给linux上传和下载文件
下载:sz中的s意为send(发送),告诉客户端,我(服务器)要发送文件 send to cilent,就等同于客户端在下载. 上传:rz中的r意为received(接收),告诉客户端,我(服务器)要 ...
- idea创建maven的web工程
然后一路点next 接下去添加tomcat 成功 控制台出现乱码的话 输入:-Dfile.encoding=UTF-8 控制台乱码解决
- php 多次导入文件导致 Cannot redeclare class
定义了类A b.php中导入了A c.php中导入了b.php c.php中导入A会报错:
- 浅谈JVM-图解类加载机制
一.目录 二.类加载机制流程 1.什么是类加载机制? JVM把class文件加载到内存里面,并对数据进行校验.准备.解析和初始化,最终能够被形成被JVM可以直接使用的Java类型的过程. 2.类加载流 ...
- [AngularJS] “路由”的定义概念、使用详解——AngularJS学习资料教程
这是小编的一些学习资料,理论上只是为了自己以后学习需要的,但是还是需要认真对待的 以下内容仅供参考,请慎重使用学习 AngularJS“路由”的定义概念 AngularJS最近真的很火,很多同事啊同学 ...
- Linux之FineBI集群部署
在企业应用中,通常单个计算机的配置是有限的,而企业应用又是高并发的需求,这个时候会通过计算机集群的方式来提高并发数,从而提高整体应用服务的性能.集群是将多台计算机作为一个整体来提供相关应用的服务.Fi ...
- svn取消文件夹关联的方法
新建个记事本,贴入以下代码,保存后重命名后缀为reg,然后在目标文件夹右键就出现了删除SVN的选项了. 代码如下: Windows Registry Editor Version 5.00 [HKEY ...
- 初识oracle重做日志文件
转自 http://blog.csdn.net/indexman/article/details/7746948 以下易容翻译自oracle dba官方文档,不足之处还望指出. 管理重做日志文件 学习 ...