以下是Windows平台下两个函数的声明:
int WSASend(
__in          SOCKET s,
__in          LPWSABUF lpBuffers,
__in          DWORD dwBufferCount,
__out         LPDWORD lpNumberOfBytesSent,
__in          DWORD dwFlags,
__in          LPWSAOVERLAPPED lpOverlapped,
__in          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
int WSARecv(
__in          SOCKET s,
__in_out      LPWSABUF lpBuffers,
__in          DWORD dwBufferCount,
__out         LPDWORD lpNumberOfBytesRecvd,
__in_out      LPDWORD lpFlags,
__in          LPWSAOVERLAPPED lpOverlapped,
__in          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine

其中lpBuffers,dwBufferCount两个参数是可以同时为空和0 的.

默认情况下,操作系统为每一个套接字分配两个缓冲区分别用于缓冲发送数据和接受数据,所谓缓冲就是:

  • 应用层的发送数据先拷贝到发送缓冲区,然后再由操作系统发送出去.
  • 远端发过来的数据先放在接受缓冲区,等待应用层调用读操作,把这些数据取走.

这两个缓冲区由操作系统管理,并且属于内核地址空间,是非分页的(Non-paged pool ).

传统模式下,我们直接调用这个两个API进行重叠IO操作,并传递我们的应用层缓冲区地址,这个时候操作系统典型的处理方法如下:

  • 发送:应用层调用WSASend,这个时候如果套接字发送缓冲区由足够的空间,操作系统将把应用层提交的数据拷贝过来,这个操作立即完成并返回成功.如果套接字的缓冲区满了,应用层提交的那块内存就会被操作系统锁住,并且返回一个WSA_IO_PENDING的错误,在发送缓冲区的数据处理完毕后,操作系统将直接将发送应用层缓冲区的数据,不再拷贝到缓冲区,这个时候应用层将会收到完成通知.如果缓冲区仍然有空间,但是也不够存放应用层请求的数据,仍然按照前一种情况处理.
  • 接收:应用层调用WSARecv,很有已经有数据在套接字接收缓冲区中了,这个时候操作系统会直接将数据拷贝过来,这个调用将返回成功,同时系统投递一个完成通知,应用在处理这个通知的时候将会知道本次操作的数据量.另一种情况是接受缓冲区没有数据,应用层提交的缓冲区就会被锁住,并且得到WSA_IO_PENDING错误,一旦这个连接收到了数据,操作系统会直接把数据拷贝用户缓冲区,并发出完成通知.

无论是发还是收,一旦应用层内存被锁住,这块内存就不能从物理内存分页出去.操作系统会限制这些被锁住的内存的数量,一旦达到这个限制,就会返回WSAENOBUFS错误.如果应用层在每一个连接上发起大量重叠IO请求,随着连接数的增长,很可能就达到这个限制的值.一方面是因为重叠IO操作数量上的增长,另一方面是因为当前系统的分页单位是固定的,即使应用层只有一个字节的操作请求,操作系统仍然需要付出一页(一般是4K)的代价.

如果服务器希望能处理非常多并发连接,可以在每个连接的读请求时投递一个0字节的读操作,即在WSARecv的时候为lpBuffers和 dwBufferCount分别传递NULL和0参数.这样做就不会存在内存锁定带来的资源紧张问题,因为没有内存需要被锁定,一旦有数据被收到,操作系 统就会投递完成通知.这个时候服务端就可以去套接字接受缓冲区取数据了,有两种方法可以得知到底有多少数据可以读,一种是通过ioctlsocket结合 FIONREAD参数去"查询",另一种就是一直读,直到得到WSAEWOULDBLOCK错 误,就表示没有数据可读了.另一方面在发送数据的时候,仍然可以采用这种方案,原因在于对端的应用可能效率非常低下,或者陷入了某个死循环,导致对方的网 络IO层迟迟不调用recv/WSARecv,受TCP协议本身的限制,服务端需要发送的数据就会一直PENDING,进而导致内存被内核锁住.采用0字 节发送方式后,应用层先投递一个空的WSASend,表示希望发送数据,操作系统一旦判断这个连接可以写了,会投递一个完成通知,此时便可以放心投递数 据,并且发送缓冲区的大小是可知的,不会存在内存锁定的问题.

这种方案适合最大化并发量,但也存在短处,首先就是数据发送和接受的时候有一个数据拷贝的代价,从网络上收到的数据 并不是直接放到应用层提交的缓冲区里.另外一个代价就是每一次读和写要经过一个先请求后实施的操作,而传统的方案是要一步到位.但正是这些差异避免了对系 统资源严重占用.

提到windows平台上的高性能IO操作,就不得不提IOCP(完成端口),上面的方案是完全适合ICOP模型 的.顺带提一下在这种模型下对同一个套接字投递多个读和写操作的情况,IOCP可以保证多个同一个句柄上的多个重叠操作在数据处理上是有序的,也就是说先 提交的重叠操作先处理,但是不保证你收到的完成通知是有序的.

零字节WSASend,WSARecv相关推荐

  1. centos下排查vsftpd出现put零字节问题的记录

    1.问题: 文件put到ftp服务器卡住,查看log(tail -n1000 /var/log/vsftpd.log |more),发现客户端put的文件是0字节: 2.查核: 1)用户和目录权限:/ ...

  2. 【功能】:前台上传文件(txt,xls,xlsx,csv,pdf)五种格式的文件 后台java解析文件,并且判断文件内容是否为零字节

    描述:前台html上传文件到后台解析文件.文件类型有txt,xls,xlsx,csv,pdf这五种类型,并且要判断文件内容是否为空,就是有文件,但是文件内容的字节为零. 首先先配置需要maven依赖. ...

  3. android mkdirs 不起作用,Android mkdirs()创建一个零字节文件而不是文件夹

    在我的 Android应用程序中,我试图在SD卡上创建以下文件夹: /mnt/sdcard/OSGiComponents/admin/felix-cache/ 这是代码: File cacheDir ...

  4. 如何将零终止的字节数组转换为字符串?

    本文翻译自:How to convert a zero-terminated byte array to string? I need to read [100]byte to transfer a ...

  5. linux删除0字节的文件,如何在linux中删除许多0字节的文件?

    I've a directory with many number of 0 byte files in it. I can't even see the files when I use the l ...

  6. 字节跳动2021年4月面试算法题库

    本文汇总了牛客2021.4.1~2021.4.30 面经考到的Leetcode题目 最终的高频题榜单数据可以在CodeTop题库(https://codetop.cc)查询,支持按部门.岗位分类筛选. ...

  7. 字符,字节和编码, ASCII码, DBCS码,SBCS码 与Unicode码

    字符,字节和编码, ASCII码, DBCS码,SBCS码 与Unicode码 http://www.regexlab.com/zh/encoding.htm 1. 编码问题的由来,相关概念的理解 1 ...

  8. Windows五种IO模型性能分析和Linux五种IO模型性能分析

    Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blo ...

  9. 一个简单的完成端口(服务端/客户端)类

    一个简单的完成端口(服务端/客户端)类 作者:spinoza 翻译:麦子芽儿, POWERCPP(后面部分内容) 下载源代码 原文网址:http://www.codeproject.com/KB/IP ...

最新文章

  1. 深度 | AI掘金,非富即亡
  2. 噪声强度(噪声功率) 噪声方差到底有什么关系?
  3. 人生第一次删好友,删的就是你!连路飞都怒了!
  4. flask的ajax的csrf代码
  5. RabbitMQ 拓展基础组件封装思路
  6. c++ switch/case 使用 string的方法
  7. 洛谷 P2894 酒店 Hotel
  8. 告别码公式的痛苦,公式OCR终于来了!
  9. AD9的PCB技巧——CAD的导入
  10. psnr--峰值信噪比
  11. 在unity中使用Excel表格
  12. POJ-3580-SuperMemo(splay的各种操作)
  13. 币种对应的转换因子(处理日元台币…
  14. windows10 安装office2021(预装正版)经验分享
  15. 动网新闻系统IWMS中实现带标题幻灯片的功能效果
  16. idea2020版本无法使用actiBPM插件问题
  17. split(),slice(),splice()的区别与应用
  18. Android内嵌H5,安卓手机返回键点击无反应、苹果手机返回键正常情况解决方案
  19. autojs ui界面漂亮模板2
  20. Python中getopt()函数的使用

热门文章

  1. GraphQL入门之GraphQL查询的规范
  2. springBoot整合Listener
  3. mysql 秒杀 隔离级别_MySQL 四种隔离级别详解,看完吊打面试官
  4. Java8函数式编程(4)--终止操作(源码)
  5. linux下qt实现计算器,QT实现计算器
  6. pd.get_dummies()
  7. Redis持久化方式的选择
  8. 使用python实现人脸检测转载
  9. Object对象具体解释(二)之clone
  10. 介绍一个基于simhash作海量文章排重的库:simhashpy