无法设置套接字connect()调用的超时

时间:2012-10-10 10:12:14

标签: c sockets connection

我已经在本机代码中编写客户端套接字程序并在android应用程序中使用它。当服务器不可用时,我在与服务器建立连接时遇到一个奇怪的问题。

当服务器不可用时,客户端connect()调用将进行折腾,它根本不会出现。我试图在互联网上搜索这个。一些链接正在解释这些步骤

  1. 将套接字设置为非阻止模式
  2. 调用连接 - 如果连接成功,则
  3. 否则将套接字设置回阻止模式。
  4. 设置套接字以进行写入设置,并将其设置为具有所需超时的select()。
  5. 如果选择出现在写入集中设置套接字,则连接成功或连接失败。
  6. 我尝试了这些步骤,但无论服务器是否正在运行,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()调用超时时出错的地方..

    赞赏任何建议或替代方法。

    谢谢。

2 个答案:

答案 0 :(得分:0)

对于处于非阻塞模式的情况,我看不到您在哪里等待连接完成。

另外,我会问在应用程序建立之前应用程序是否应该执行其他操作?如果是这样,我会考虑使用类似pthreads的东西将SocketConnect函数重组为一个单独的线程。如果您的应用程序的行为完全取决于客户端连接,我会考虑在连接之前将套接字从非阻塞切换到阻塞,并保持呼叫在SocketConnect中连接。

答案 1 :(得分: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
}
}