找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3761|回复: 7

连接建立后首次启动异步读操作总是失败!

[复制链接]
发表于 2009-8-18 18:05:29 | 显示全部楼层 |阅读模式
奇怪的问题,之前在局域网内运行了几个月完全没问题,服务器放到公网后客户端与服务器建立连接总是失败:在 open 中initiate_read_stream调用中启动异步读操作总是失败,返回 -1,导致连接被终止。之前一直没这个问题,最后尝试在首次启动异步读操作之前休眠4500毫秒,居然就不再出现问题了。这到底是为何?

客户端操作系统是 Xp ,ACE 版本是 5.6.9。大家帮忙一下,谢谢!
void
ACEChannel_Handler::open(ACE_HANDLE new_handle, ACE_Message_Block& message_block) {
if (this->reader_.open((*this), new_handle, 0, this->proactor()) == -1) {
  ACE_ERROR(
   (LM_ERROR, ACE_TEXT("%p\n"),
   ACE_TEXT("ACEChannel_Handler::open-Read")));
} else if (this->writer_.open((*this), new_handle, 0, this->proactor()) == -1) {
  ACE_ERROR(
   (LM_ERROR, ACE_TEXT("%p\n"),
   ACE_TEXT("ACEChannel_Handler::open-Write")));
} else {
  //::Sleep(4500); 休眠之后 initiate_read_stream 才会成功。
  this->initiate_read_stream();
}
this->check_destroy();
}

int
ACEChannel_Handler::initiate_read_stream() {
ACE_Guard<ACE_Recursive_Thread_Mutex> lock(this->lock_);
if (this->read_mblk_.space() <= 0) {
  this->read_mblk_.size(this->read_mblk_.size() + 521);
}

if (this->reader_.read(this->read_mblk_, this->read_mblk_.space()) == -1) {
  ACE_ERROR_RETURN(
   (LM_ERROR, ACE_TEXT("%p%d\n"),
   ACE_TEXT("ACEChannel_Handler::initiate_read_stream"), GetLastError()),
   -1);
}

++(this->io_counter_);
return 0;
}
发表于 2009-8-18 21:21:18 | 显示全部楼层
奇怪问题,经常有简单答案。
查看环境是否可用,比如防火墙等。
查看错误代码,使用telnet链接测试。
 楼主| 发表于 2009-8-19 09:48:36 | 显示全部楼层
用TELNET测试正常。
 楼主| 发表于 2009-8-19 09:49:24 | 显示全部楼层
用同步连接的话也不会出现问题。
发表于 2009-8-19 11:10:03 | 显示全部楼层
怀疑跟时序、线程调度有关。因为没有更多代码,不好判断了。查查错误代码,追踪一下呢?
发表于 2009-8-19 13:04:36 | 显示全部楼层
同意老大的看法,
从配置环境上找找问题吧。
发表于 2009-8-20 14:16:48 | 显示全部楼层
猜测一下,可能是客户端发起connect,发出最后一个ack,认为3次握手结束了,连接建立,立刻read。但服务器还没调用accept(可能还没收到这个ack,也可能收到了但还在backlog中),所以read失败。在局域网中握手很快,但公网中这个ack传过去可能比较慢,而客户端逻辑是发送ack后立刻read,所以有个时间差。
LZ可以看下errno是不是EAGAIN或EWOULDBLOCK,如果是的话很可能是以上原因,因为异步读模式不阻塞,当不能立刻成功时就会返回-1,错误码为EAGAIN或EWOULDBLOCK。
“用同步连接的话也不会出现问题。”是指用ACE_Connector和ACE_Acceptor么?

PS:我以前也遇到过类似情况,不过是在一端handle_write_stream中立刻关闭连接。这样对端读的时候读不到,报错连接已关闭。如果在handle_write_stream中加个sleep(1),然后再关闭连接,就没问题了。原因肯定是一些具体实现细节问题,反正解决了就懒得深究了。
 楼主| 发表于 2009-8-21 19:45:43 | 显示全部楼层
原帖由 wishel 于 2009-8-20 14:16 发表
猜测一下,可能是客户端发起connect,发出最后一个ack,认为3次握手结束了,连接建立,立刻read。但服务器还没调用accept(可能还没收到这个ack,也可能收到了但还在backlog中),所以read失败。在局域网中握手很快,但公网中这个ack传过 ...

很有可能,我试下。
非常感谢你的回复!
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

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

GMT+8, 2024-11-23 00:03 , Processed in 0.061432 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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