对于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);之前,导致后面的发送请求不执行了!
随机推荐
- plupload如何删除一条数据
FilesRemoved用了发现不成功,删除图片这么重要怎能如此 看到老外提的另一个问题发现这个问题解决办法,特此备注以供不会的童鞋参考 uploader.bind('FilesAdded', fun ...
- oracle中scott用户的创建
原创作品,转载请在文章开头显眼位置注明出处:https://www.cnblogs.com/sunshine5683/p/10046716.html 今天,接着上次的学习进度继续前进,在此过程中,使用 ...
- Spring学习手札(一)
Spring能做什么 1. 能根据配置文件创建及组装对象之间的依赖关系: 2. 面向切面编程,能帮助我们无耦合的实现日志记录,性能统计,安全控制等: 3. 提供第三方数据访问框架(如Hibernate ...
- vscode 支持es6语法
在首选项中 设置: "jshint.enable": false, 在根目录中建立eslintrc.yml parser: babel-eslint parserOptions: ...
- PHP ServerPush (推送) 技术的探讨[整理]
需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ...
- js中var、let、const区别
javascript中有三种声明变量的方式:var.let.const 1.var 作用域:全局或局部 var的作用域可以是全局或是局部,以下分四种情况说明: (1).当var关键字声明于函数内时是局 ...
- 宝塔面板nginx配置安装Discuz
Discuz!在Nginx下的Rewrite 需要说明的是,下网上以前一直流传的Rewrite都是有误的. 下面的Rewrite中百分号前面多了个转移字符"",这在Apache中是 ...
- opencv3.2.0形态学滤波之膨胀
//名称:膨胀 //日期:12月21日 //平台:QT5.7.1+opencv3.2.0 /* 膨胀(dilate)的含义: 膨胀就是求局部最大值的操作,就是将图像(或图像的一部分,A)与核 B 进行 ...
- Redis在windows下安装过程(转载)
转载自(http://www.cnblogs.com/M-LittleBird/p/5902850.html) 一.下载windows版本的Redis 官网以及没有下载地址,只能在github上下载, ...
- Ubuntu 添加删除用户 How to Add and Delete Users on Ubuntu 16.04
Introduction One of the most basic tasks that you should know how to do on a fresh Linux server is ...