【发布时间】:2012-10-10 10:12:14
【问题描述】:
我已经用本机代码编写了客户端套接字程序,并在 android 应用程序中使用它。当服务器不可用时与服务器建立连接时,我遇到了一个奇怪的问题。
当服务器不可用时,客户端 connect() 调用将被折腾,它根本不出来。我试图在互联网上搜索这个。一些链接解释了这些步骤
- 将套接字设置为非阻塞模式
- 调用连接 - 如果连接成功则很好
- 否则将套接字设置回阻塞模式。
- 为写入集设置套接字并将其提供给 select() 并要求超时。
- 如果选择出来时在写入集中设置了套接字,则连接成功或连接失败。
我尝试了这些步骤,但无论服务器是否正在运行,select() 调用总是只出现超时。我需要你的帮助来解决这个问题。
这是我正在使用的部分代码
bool SocketConnect()
{
... Creating the socket ....
int opts;
if( (opts = fcntl(clientsocket,F_GETFL) < 0 )
{
return false;
}
// setting socket to non-block mode
if( fcntl(clientsocket,opts | O_NONBLOCK) < 0 )
{
return false;
}
//calling connect
int ret = connect(clientsocket,(const sockaddr*)&serveraddr,sizeof(serveraddr));
if( ret < 0 )
{
if( errno != EINPROGRESS )
{
return false;
}
}
if( ret == 0 )
{
//connection successful set the socket to block mode
fcntl(clientsocket,F_SETFL,opts);
return true;
}
//set the socket to block mode
if( fcntl(clientsocket,F_SETFL,opts) < 0 )
{
return false;
}
fd_set writeset;
FD_ZERO(&writeset);
FD_SET(clientsocket,&writeset);
timeval val.
val.tv_sec = 5;
val.tv_usec = 0;
int sret = select(clientsocket+1,NULL,&writeset,NULL,&val);
if( sret > 0 )
{
if( FD_ISSET(clientsocket,&writeset) )
{
fcntl(clientsocket,F_SETFL,opts);
return true;
}
}
return false;
}
当服务器可用时,如果我使用阻塞的连接调用(不使用上述任何步骤),建立连接几乎不需要 1 秒。
如果我使用上述步骤进行连接,则当服务器可用时,如果我给 5 秒时间连接未建立,则事件。事件选择也不等5秒,马上出来返回值0。
请查看此代码,让我知道我在设置 connection() 调用超时时到底哪里出错了..
感谢任何建议或替代方法。
谢谢。
【问题讨论】:
-
我发现 connect() 上的 linux 文档完全错误。当非阻塞连接()上发生某些事情时,您不会收到写入事件,您会收到一个读取事件 - 即便如此,我似乎还记得一些未发出读取事件的极端情况。 (但请记住,超时的 TCP SYN 可能需要几分钟,超时的 ARP 请求也可能需要几秒钟 - 在很多情况下 TCP/IP 堆栈无法在 connect() 上提供近乎即时的反馈)
标签: c sockets connection