在TCP服务中,如果服务器主机崩溃或者崩溃后重启,如果恰好一直与客户机没有数据交换,则客户机该如何去发现服务器的情况?
通过设置socket的SO_KEEPALIVE属性可解决该问题。
int nkeepalive=SO_KEEPALIVE;
setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(char *)nkeepalive,sizeof(int));
//检测对方主机是否崩溃(即使客户机没有发数据给服务器),
//当服务器崩溃后又重启,客户机也能检测到,若没数据交换,
//每2小时发送一个驳斥存活探测分节(keepalive probe),
//避免(服务器)永远阻塞于TCP连接的输入
下面是关于send(),recv()函数的标志设置的一个实例说明:
客户端:
int opt=1000;
setsockopt(sockfd,SOL_SOCKET,SO_SNDTIMEO,(char *)&opt,sizeof(int));
//设置发送时限,1s
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&opt,sizeof(int));
//设置接收时限,1s
pid=fork();
if(pid==-1){
perror("fork");
exit(1);
}
else if(pid==0){
//发消息给服务端
if((sendbytes=send(sockfd,"hello world\n",MAXDATASIZE,MSG_DONTWAIT))==-1){
//MSG_DONTWAIT设置发送方式是非阻塞的,如此可不用设置讨接字的非阻塞属性
perror("send");
exit(1);
}
}else{
sleep(3);
if(recv(sockfd,buf,MAXDATASIZE,MSG_DONTWAIT)==-1){
perror("recv");
exit(1);
}
fprintf(stderr,"recv %s from %s \n",buf,inet_ntoa(serv_addr.sin_addr));
}
有接收有发送
服务端:
if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))==-1){
perror("recv");
exit(1);
}
printf("receveived: %s\n",buf);
仅接收,不发送
客户端执行结果:
zlm8715@zlm8715-desktop:~/zlmdata$ ./client 192.168.199.129
connect 192.168.199.129 is success!
recv: Resource temporarily unavailable
此处接收错误,是因为客户端接收的flags设置为MSG_DONTWAIT,即非阻塞,而且设置了接收、发送时限为1s。
若flags设为0,则客户端会一直阻塞在recv().
阅读(721) | 评论(0) | 转发(0) |