连接建立后首次启动异步读操作总是失败!
奇怪的问题,之前在局域网内运行了几个月完全没问题,服务器放到公网后客户端与服务器建立连接总是失败:在 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;
}
奇怪问题,经常有简单答案。
查看环境是否可用,比如防火墙等。
查看错误代码,使用telnet链接测试。 用TELNET测试正常。 用同步连接的话也不会出现问题。 怀疑跟时序、线程调度有关。因为没有更多代码,不好判断了。查查错误代码,追踪一下呢? 同意老大的看法,
从配置环境上找找问题吧。 猜测一下,可能是客户端发起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),然后再关闭连接,就没问题了。原因肯定是一些具体实现细节问题,反正解决了就懒得深究了。 原帖由 wishel 于 2009-8-20 14:16 发表 http://www.acejoy.com/bbs/images/common/back.gif
猜测一下,可能是客户端发起connect,发出最后一个ack,认为3次握手结束了,连接建立,立刻read。但服务器还没调用accept(可能还没收到这个ack,也可能收到了但还在backlog中),所以read失败。在局域网中握手很快,但公网中这个ack传过 ...
很有可能,我试下。
非常感谢你的回复!
页:
[1]