非阻塞模式下connect 成功失败判断

将一个socket 设置成 阻塞模式 非阻塞模式, 使用fcntl方法,即:

设置成非阻塞模式:

先用fcntl的F_GETFL获取flags,用F_SETFL设置flags|O_NONBLOCK;        

即:

 

      flags = fcntl(sockfd, F_GETFL, 0);                        //获取文件的flags值。

      fcntl(sockfd, F_SETFL, flags O_NONBLOCK);   //设置成非阻塞模式;

同时在接收和发送数据时,需要使用MSG_DONTWAIT标志

即:

      在recv,recvfrom和send,sendto数据时,将flag设置为MSG_DONTWAIT。

设置成阻塞模式:

 

先用fcntl的F_GETFL获取flags,用F_SETFL设置flags&~O_NONBLOCK;      

即:

     flags  = fcntl(sockfd,F_GETFL,0);                          //获取文件的flags值。

     fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK);    //设置成阻塞模式;            

同时在接收和发送数据时,需要使用阻塞标志

即:

        在recv,recvfrom和send,sendto数据时,将flag设置为0,默认是阻塞。       

 

在将socket设置成非阻塞模式后,每次的对于sockfd 的操作都是非阻塞的;

非阻塞模式下:

connect   

       =0   当返回0时,表示立即创建了socket链接,

       <0   当返回-1时,需要判断errno是否是EINPROGRESS(表示当前进程正在处理),否则失败

       例如:下面会有select或epoll监听fd是否建立链接,

        select监听connect是否成功的例子,注意getsockopt验证,因为三次握手的第三个ACK有可能会丢失,但是客户端认为链接已经建立:

int ret = ::connect(_socket_fd, add.addr(), add.length());
if(ret == 0)
{
            //建立链接成功
}
else if(ret < 0 && errno == EINPROGRESS)          //errno == EINPROGRESS表示正在建立链接
{
     // 等待连接完成,errno == EINPROGRESS表示正在建立链接
     fd_set set;
     FD_ZERO(&set);
     FD_SET(_socket_fd,&set);  //相反的是FD_CLR(_sock_fd,&set)


     time_t = 10;          //(超时时间设置为10毫秒)
     struct timeval timeo;
     timeo.tv_sec = timeout / 1000; 
     timeo.tv_usec = (timeout % 1000) * 1000;

 

     int retval = select(_socket_fd + 1, NULL, &set, NULL, &timeo);           //事件监听
     if(retval < 0)   
     {
            //建立链接错误close(_socket_fd)
     }
     else if(retval == 0) // 超时
     {
            //超时链接没有建立close(_socket_fd)
     }

     //将检测到_socket_fd读事件或写时间,并不能说明connect成功
     if(FD_ISSET(_socket_fd,&set))
     {
           int error = 0;
           socklen_t len = sizeof(error);
           if(getsockopt(_socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
           {
                  //建立简介失败close(_socket_fd)
           }
           if(error != 0) // 失败
           {
                  //建立链接失败close(_socket_fd)
           }
           else
            {
                  //建立链接成功
            }
     }
}
else
{
      //出现错误 close(_sock_fd)
}


你可能感兴趣的:(socket,connect)