2012-10-10 27 views
0

我已经在本机代码中编写了客户端套接字程序并在Android应用程序中使用它。当服务器不可用时与服务器建立连接时,我遇到了一个奇怪的问题。无法为套接字connect()调用设置超时

当服务器不可用时,客户端的connect()调用就是抛弃它,它根本就没有出现。我试图在互联网上搜索这个。有些链接是解释这些步骤

  1. 设置插座非 - 块模式
  2. 调用connect - 如果连接成功,精细
  3. 否则设置插座回框模式。
  4. 设置写入套接字并将其设置为select()并需要超时。
  5. 如果选择与写集中的套接字一起出现,则连接成功或连接失败。

我试过这些步骤,但无论服务器在运行还是不运行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。

请仔细阅读该代码,让我确切地知道我在设置超时连接脚麻()调用..

任何建议或实现的替代方法,赞赏。

谢谢。

+0

我发现Linux上的文档连接()是扁平错误。当一个非阻塞的connect()发生什么事情时,你不会得到一个写事件,你会得到一个读事件 - 即使这样,我似乎还记得一些发生read事件的情况。(请记住,超时的TCP SYN可能需要几分钟的时间,超时的ARP请求也可能需要几秒钟的时间 - 有很多情况下TCP/IP堆栈无法提供近乎即时的connect()反馈) – nos

回答

0

使用警报来中断连接。这里是示例代码

#define CONNECT_TIMEOUT 4 

static void AlarmHandler(int sig) 
{ 
sTimeout = 1; 
} 
. 
. 
. 
signal(SIGALRM, AlarmHandler); 
sTimeout = 0; 
alarm(CONNECT_TIMEOUT); 
if (connect(sock, (struct sockaddr *) &server, sizeof(server))) 
{ 
if (sTimeout) { 
NSLog(@"timeout connecting stream socket"); //If connect will remain blocked for 4 seconds after 4 seconds this condition will be triggered 
} 
} 
0

对于您处于非阻塞模式的情况,我没有看到您在等待连接完成的位置。

此外,我会问在连接建立之前应用程序应该做些什么吗?如果是这样,我会考虑使用类似pthreads的方式将SocketConnect函数重构为单独的线程。如果您的应用程序的行为完全取决于客户端连接,我会考虑在连接之前将套接字从非阻塞切换到阻塞,并保持呼叫在SocketConnect中连接。

+0

他正在调用connect ()在非阻塞模式下,这导致connect()立即返回,并推迟连接完成(或超时)到select()调用 – nos

+0

嗨,感谢您的回复。我通过其他方式解决了此问题。现在我正在使用setsockopt设置读写操作的超时时间。现在如果服务器在超时内没有响应,连接就会出现... :-) – Harish

相关问题