平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

建立在TCP SOCKET上的完成端口的问题

假设对该Socket依序连续发起两次以上的异步写操作,即发送数据,最终数据是否按顺序发出,客户端是否能按顺序收到数据?
1.书本的理论上异步IO操作不保证完成的顺序性.
2.实际测试运行数据消息是按序收到的,但实践没有100%的理论逻辑保证,程序有逻辑上的崩溃可能.
3.如果不能对TCP Socket进行连续异步写数据,且保证最终是有序的发送,那么Socket的异步完成端口没有实用价值.如果要等上次异步写操作完成,才能发送第2个数据,同步方式的方案最佳.完成端口的优势仅在其流量上.
4.假设用一个for循环连续发起1000次以上的异步写操作,意味着大量的系统资源被耗用,对服务器而言几千次很平常.

研究碰撞反应受阻,只好想些知识极限范围内的问题.

补:
发送顺序肯定和投递顺序一致的,这个是系统保证的,但完成通知的次序是不保证和投递次序一致的。- WINDOWS网络编程(第2版)

// 下段摘自网络论坛
其实在使用IOCP的时候,为每个SOCKET连接建立一个发送队列,发完一个包后才发第2个,这样从单个SOCKET来看,是成了阻塞的,但是从整个系统来看,比如你有1万个连接,那么对于单个连接来说,是不是组塞的问题都不大。因为当连接数多了后,你考虑的问题不是单个SOCKET要有多块,而是系统资源和带宽如何平均地分配给这么多个连接。

posted on 2006-02-02 21:02 linghuye 阅读(3253) 评论(5)  编辑 收藏 引用 所属分类: 编程札记

评论

# re: 建立在TCP SOCKET上的完成端口的问题  回复  更多评论   

不错。学习。
2006-02-06 19:14 | nbw

# re: 建立在TCP SOCKET上的完成端口的问题  回复  更多评论   

一直在拜读楼主的文章,感觉能学到很多东西的说。
就我对IOCP的使用,提出一些愚见,说错了楼主不要见怪。:)
TCP本身保证了数据的准确,绝对不会丢包,数据通过Socket缓冲到网卡的缓冲区内,然后由网卡负责发送。大多数情况下是顺序的,但也有一些网卡会出现一些发送顺序问题,可能是网卡内部机制或者BUG引起的。一般在网络协议上追加时间戳能用软件的方法避免这个问题。
IOCP对数据吞吐是很高效的,起码在WIN平台上这样。
2006-02-10 17:37 | freeeyes

# re: 建立在TCP SOCKET上的完成端口的问题  回复  更多评论   

对的,TCP协议本身是保证了数据的准备和有序性.
但IOCP调用本身却是异步的,它发数据用WriteFile OVERLAP调用方式,而不是socket send的同步.
两次异步WriteFile调用,数据到达TCP协议层时的顺序就不明确了.
如果数据能按异步函数调用顺序到达协议层,那TCP会保证数据按序发出.
不知有无文档说明Windows的WriteFile实现保证异步调用时数据到TCP协议层也是依序的. 异步WriteFile是直接返回,还是把数据送到TCP层才返回,还是怎的.嗯,原子性操作不明确.
2006-02-11 11:10 | 平民程序

# re: 建立在TCP SOCKET上的完成端口的问题  回复  更多评论   

IOCP是一种对IO端口的操作方式,它本身是异步的,它可以应用于TCP。也可以用于文件读取或者其他的IO操作。不过就我的经验,IOCP还是能够保证顺序的。
不知道楼主想研究那部分原子性,如果是TCP,推荐楼主看看《TCP/IP详解,卷五》,网上有电子版的,里面有一些关于IOCP应用的描述。
2006-02-21 10:04 | freeeyes

# re: 建立在TCP SOCKET上的完成端口的问题  回复  更多评论   

也来胡乱聊聊,

1.书本的理论上异步IO操作不保证完成的顺序性.

注意是完成的顺序性,也就是说发送时保证了顺序性(因实际上是对每个socket建立了队列,每次WSASend,都会进入到队列,而队列保证了顺序性),但是系统给overlap设置状态以激活workthread时,是不能保证先发送的overlap先进入到workthread。只要想想当某个Send结束后上尚未来的及设置状态,线程就被切换出去时的情况。

2.实际测试运行数据消息是按序收到的,但实践没有100%的理论逻辑保证,程序有逻辑上的崩溃可能.

既然发送保证了顺序性,接收肯定是按序收到。

3.如果不能对TCP Socket进行连续异步写数据,且保证最终是有序的发送,那么Socket的异步完成端口没有实用价值.如果要等上次异步写操作完成,才能发送第2个数据,同步方式的方案最佳.完成端口的优势仅在其流量上.

完全可以异步写数据,退一步说,即便是不能异步写,完成端口的重大意义也是存在的,同步send会导致当前的流程被hold住,你只要想一下当某个网络状况十分不好的client链接到你的server端,同步发送,必须要等待所有的tcp流程结束,才能返回或者成功或者失败的结果,此时其他的client不得不在旁边等着。

4.假设用一个for循环连续发起1000次以上的异步写操作,意味着大量的系统资源被耗用,对服务器而言几千次很平常.

这个我还没有仔细思考。。。。。
2009-02-12 16:27 | ddk
只有注册用户登录后才能发表评论。