非阻塞模式,如果暂时没有数据,返回的值也会是<=0的,如果用阻塞模式的话,返回<=0的值是可以认为socket已经无效了。
当使用 select()函数测试一个socket是否可读时,如果select()函数返回值为1,
且使用recv()函数读取的数据长度为0 时,就说明该socket已经断开。
经过代码试验,如果进程受到一些信号时,例如:EINTR,recv()返回值小于等于0时,这是就需要判断 errno是否等于 EINTR , 如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的,socket连接还是正常的,不应close掉socket连接。
如果write,我觉得还有一些情况需要考虑,那就是写的太快的时候,有可能buffer写满了,这是,errno是EAGAIN,可以根据实际需要,如果errno是EAGAIN的话,再写几次。
当然,read的时候也有类似write的情况,需要check一下errno,如果是EAGAIN或者EINTR,最好不要立刻终止操作,再尝试一下!
这是我写的一个代码!
int SocketConnected(int sock) { int res,recvlen; char buf[20] = {'\0'}; struct timeval timeout={3,0}; fd_set rdfs; FD_ZERO(&rdfs); FD_SET(sock,&rdfs); res = select(sock+1,&rdfs,NULL,NULL,&timeout); if(res > 0){ recvlen = recv(sock,buf,sizeof(buf),0); if(recvlen > 0){ printf("socket connected\n"); return 1; } else if (recvlen < 0 ){ if(errno == EINTR){ printf("socket connected\n"); return 1; }else { printf("socket disconnected! connect again!\n"); return 0; } } else if (recvlen == 0){ printf("socket disconnected!connect again\n"); return 0; } } else if(res == 0 ){ //time out printf("socket connected\n"); return 1; } else if(res < 0){ if (errno == EINTR){ printf("socket connected\n"); return 1; }else{ printf("socket disconnected ! connect again!\n"); return 0; } } return 0; }
另外还有另外一种检测方法,也比较好用,但是在2.4内核在编译过程中可能有问题。
头文件 Linux/tcp.h、
int SocketConnected(int sock) 346 { 347 struct tcp_info info; 348 int len=sizeof(info); 349 if(sock<=0){ 350 return 0; 351 } 352 memset(&info,0,sizeof(info)); 353 getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len); 354 if(info.tcpi_state== 1) { 355 printf("socket connected\n"); 356 return 1; 357 } else { 358 printf("socket disconnected\n"); 359 return 0; 360 } 361 }
以上是总结,有问题请及时提出!