Chinaunix首页 | 论坛 | 博客
  • 博客访问: 353581
  • 博文数量: 82
  • 博客积分: 3353
  • 博客等级: 中校
  • 技术积分: 742
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-20 19:13
文章分类

全部博文(82)

文章存档

2015年(1)

2014年(1)

2013年(1)

2012年(12)

2011年(3)

2010年(25)

2009年(37)

2008年(2)

我的朋友

分类: LINUX

2009-07-07 21:01:48

   在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) |
给主人留下些什么吧!~~