找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3623|回复: 5

异步读写的两个奇怪问题

[复制链接]
发表于 2008-8-5 22:45:08 | 显示全部楼层 |阅读模式
参考ace(5.6)自带的example/Reactor/Proactor/test_proactor.cpp

1.ACE_Asynch_Acceptor<Handler>,在接受新连接之后会从对方socket预读一个message blok(大小512),然后在调用Handler的open()的时候把这个message block作为参数传递过去。此时该Handler要先把这一部分数据处理了,然后继续下面的动作(一般是继续读),不然的话就会丢失数据。例子中是通过自己做了一个fake的result来处理的。
2.ACE_Asynch_Write_Stream在对socket进行write的时候,最后一次write完成后(complete),不要立即退出程序。否则接收方会因为对方连接断掉,无法读到数据,报错: (ACE_Asynch_Read_Stream::read: 指定的网络名不再可用。)一般当处理的数据较多(文件较大)时容易产生这样的错误。这时可在最后一次write完成后,在handle_write_stream退出前,sleep一到几秒钟。等接收方收完在退出。
该例子中因为同时有ACE_Asynch_Transmit_File,所以没有这样的情况。但是如果把有关ACE_Asynch_Transmit_File的内容屏蔽掉,就可以看到这个问题。把Sender::handle_write_stream()中最后一段,this->stream_write_done_ = 1;之后加一句ACE_OS::sleep(1); 问题解决。
 楼主| 发表于 2008-9-12 10:23:59 | 显示全部楼层
发现这个帖子里有问题1的详细解释:
http://acejoy.com/bbs/viewthread.php?tid=821&extra=page%3D1

对ACE的这个open的实现感到不解,为何缺省时要抛出附带数据?这样很难让用户理解
按道理应该是缺省时不抛,但可以由用户自定义选择是否抛和抛出大小。
发表于 2008-9-12 11:12:12 | 显示全部楼层
我的理解就是OS的约束关系和一些设计考虑。
如果改成你想要的设计,想一下如下情景:
客户要求预读4K的数据,而且读取完成后返回。但是对端只返回了1K,剩下的就不发了,一直在那里耗着等待。
这样,你就无法对系统的网络连接处理器对象做什么事情了。因为连open方法都调不出来,只好干等,相当于死在那里了。这种设计是很不安全而且被动的。
相反,当前的这种实现,把决定权交给了使用者。如果收回的信息数量不足,需要时候,他至多再发一次预读即可。如果有人恶意连接,你可以进行测试和超时,进行防范。
以上是我的理解。
 楼主| 发表于 2008-9-12 15:51:53 | 显示全部楼层
我的疑惑主要是为什么要默认预读?
一般情况是客户先connect,然后send。服务器先accept,然后recv。
而预读时,服务器在accept的时候,在recv之前,进行了部分预读。这好像不大符合常规习惯。
其实可以完全不用预读,accept只做接受和建立连接,读数据只用recv来实现。如果recv收到的字节数不足,再重新发起recv就可以了,直到最后收到足够的数据。
发表于 2008-9-13 07:46:23 | 显示全部楼层
参见Windows网络编程,第六章 - Scalable Winsock Applications,第一节 - APIs and Scalability
预读能提高性能。
 楼主| 发表于 2008-9-17 17:25:26 | 显示全部楼层
呵呵,明白了,原来是为了性能的考虑。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-23 21:49 , Processed in 0.215032 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表