IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    jsh13417发表于 2014-06-13 16:56:47
    love 0
    将一个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) }


沪ICP备19023445号-2号
友情链接