如何判断socket已经断开
1个回答
展开全部
非阻塞模式,如果暂时没有数据,返回的值也会是<=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 }
当使用 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 }
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询