select read write

[cpp]  view plain copy
  1. <p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; "><span style="font-size:14px; "><strong>1. 服务器</strong></span></p><p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; "> 当有新连接来的时候,通过在select上轮循写的fd(文件描述符)发送一句欢迎词。然后每次受到客户端的数据后,把接受到的数据返回给客户端。演示了在select上轮循写的操作。</p><p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; ">对于监视读操作,只有当数据来的时候,读操作的fd才会返回.而对于写的操作fd,则是轮询。</p>  
[cpp]  view plain copy
  1. /* 
  2.  the example is writed by minrongf,date: 20090214 
  3. #filename: selectsvr.c 
  4.  * */  
  5. #include <stdio.h>   
  6. #include <stdlib.h>   
  7. #include <errno.h>   
  8. #include <string.h>   
  9. #include <netdb.h>   
  10. #include <sys/types.h>   
  11. #include <netinet/in.h>   
  12. #include <sys/socket.h>   
  13. #include <sys/time.h>  
  14. typedef int SOCKET;  
  15. #define MAXBUFSIZE 1024  
  16. #define NLISTEN 1024  
  17. #define isvalidsock(s)  ( ( s ) > 0 )  
  18. void set_address( char *hname, char *sname,struct sockaddr_in *sap, char *protocol )  
  19. {  
  20.     struct servent *sp;  
  21.     struct hostent *hp;  
  22.     char *endptr;  
  23.     short port;  
  24.   
  25.     bzero( sap, sizeof( *sap ) );  
  26.     sap->sin_family = AF_INET;  
  27.     if ( hname != NULL )  
  28.     {  
  29.         if ( !inet_aton( hname, &sap->sin_addr ) )  
  30.         {  
  31.             hp = gethostbyname( hname );  
  32.             if ( hp == NULL )  
  33.                 error( 1, 0, "unknown host: %s/n", hname );  
  34.             sap->sin_addr = *( struct in_addr * )hp->h_addr;  
  35.         }  
  36.     }  
  37.     else  
  38.         sap->sin_addr.s_addr = htonl( INADDR_ANY );  
  39.     port = strtol( sname, &endptr, 0 );  
  40.     if ( *endptr == '/0' )  
  41.         sap->sin_port = htons( port );  
  42.     else  
  43.     {  
  44.         sp = getservbyname( sname, protocol );  
  45.         if ( sp == NULL )  
  46.             error( 1, 0, "unknown service: %s/n", sname );  
  47.         sap->sin_port = sp->s_port;  
  48.     }  
  49. }  
  50.   
  51. SOCKET tcp_server( char *hname, char *sname )  
  52. {  
  53.     struct sockaddr_in local;  
  54.     SOCKET s;  
  55.     const int on = 1;  
  56.   
  57.     set_address( hname, sname, &local, "tcp" );  
  58.     s = socket( AF_INET, SOCK_STREAM, 0 );  
  59.     if ( !isvalidsock( s ) )  
  60.         error( 1, errno, "socket call failed" );  
  61.   
  62.     if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,  
  63.         ( char * )&on, sizeof( on ) ) )  
  64.         error( 1, errno, "setsockopt failed" );  
  65.   
  66.     if ( bind( s, ( struct sockaddr * ) &local,  
  67.          sizeof( local ) ) )  
  68.         error( 1, errno, "bind failed" );  
  69.   
  70.     if ( listen( s, NLISTEN ) )  
  71.         error( 1, errno, "listen failed" );  
  72.   
  73.     return s;  
  74. }  
  75.   
  76.   
  77.   
  78. int main(int argc,char**argv)  
  79. {  
  80.    int i,maxi,maxfd,listenfd,connfd,sockfd;  
  81.    int nready,client[FD_SETSIZE];  
  82.    fd_set rset,alllset,wset,wsetsave;  
  83.    char buf[MAXBUFSIZE];  
  84.    socklen_t clilen;  
  85.    struct sockaddr_in servaddr,cliaddr;  
  86.    int rval;  
  87.    struct timeval to;  
  88.    int n = 0;  
  89.    listenfd =  tcp_server(NULL,"5000");  
  90.   
  91.   
  92.    FD_ZERO(&alllset);  
  93.    FD_ZERO(&wsetsave);  
  94.    FD_SET(listenfd,&alllset);  
  95.    maxfd = listenfd;  
  96.    for(i = 0; i < FD_SETSIZE;i++)  
  97.        client[i] = -1;  
  98.    maxi = -1;  
  99.    while(1)  
  100.    {  
  101.     FD_ZERO(&rset);  
  102.         rset = alllset;  
  103.     wset = wsetsave;  
  104.     printf("server waiting...,maxfd:%d/n",maxfd);  
  105.     nready = select(maxfd+1,&rset,&wset,NULL,NULL);  
  106.     if(FD_ISSET(listenfd,&rset))  
  107.     {  
  108.        clilen = sizeof(cliaddr);  
  109.        connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);  
  110.        for(i = 0; i< FD_SETSIZE; i++)  
  111.            {  
  112.            if(client[i] < 0)  
  113.            {  
  114.                         client[i] = connfd;  
  115.             break;  
  116.            }  
  117.        }  
  118.        if(i == FD_SETSIZE)  
  119.        {  
  120.               printf("too many clients /n");  
  121.               exit(1);  
  122.        }  
  123.            FD_SET(connfd,&alllset);  
  124.        FD_SET(connfd,&wsetsave);  
  125.        printf("addinng client on fd %d/n",connfd);  
  126.        if(connfd > maxfd)  
  127.               maxfd = connfd;  
  128.        if( i > maxi)  
  129.                maxi = i;  
  130.        if(--nready <= 0)  
  131.                 continue;  
  132.        
  133.        }  
  134.        for(i = 0; i <= maxi; i++)  
  135.        {  
  136.            if((sockfd = client[i]) < 0 )  
  137.           continue;  
  138.       if(FD_ISSET(sockfd,&rset))  
  139.       {  
  140.               bzero(buf,100);  
  141.               if((n = recv(sockfd,buf,MAXBUFSIZE,0)) <= 0)  
  142.           {  
  143.                   close(sockfd);  
  144.             FD_CLR(sockfd,&alllset);  
  145.             client[i] = -1;  
  146.             printf("recv error,client:%d exit/n",sockfd);  
  147.             
  148.           }  
  149.           else  
  150.           {  
  151.                   sleep(2);  
  152.                   printf("serving client read on fd %d,recv datalen: %d,data:%s /n",sockfd,n,buf);  
  153.           write(sockfd,buf,n);  
  154.           }  
  155.           if(--nready <= 0 )  
  156.           break;      
  157.   
  158.           }  
  159.       else if(FD_ISSET(sockfd,&wset))  
  160.       {  
  161.               char buf1[100] = {""};  
  162.               sprintf(buf1,"Welcome the selectsvr .../n");  
  163.               if((n = send(sockfd,buf1,strlen(buf1),0)) <= 0)  
  164.               {  
  165.                    close(sockfd);  
  166.            FD_CLR(sockfd,&wsetsave);  
  167.            printf("send error,client:%d exit/n",sockfd);  
  168.           }  
  169.           else  
  170.           {  
  171.                    FD_CLR(sockfd,&wsetsave);  
  172.                    printf("serving client write on fd %d,data:%s/n",sockfd,buf1);  
  173.           }  
  174.           sleep(5);  
  175.       }  
  176.   
  177.     }  
  178.   }   
  179.   
  180. }  
[cpp]  view plain copy
  1. <span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; ">通过: gcc selectsvr.c -o selectsvr 编译得到执行文件selectsvr</span>  
[cpp]  view plain copy
  1. <span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px; "><span style="color: rgb(51, 51, 51); font-family: Arial; line-height: 26px; text-align: left;font-size:14px; "> 2. 客户端</span>  
  2. </span>  
[cpp]  view plain copy
  1. /* 
  2.  the example is writed by minrongf,date: 20090214 
  3. #filename:selectcli.c 
  4.  * */  
  5. #include <stdio.h>   
  6. #include <stdlib.h>   
  7. #include <errno.h>   
  8. #include <string.h>   
  9. #include <netdb.h>   
  10. #include <sys/types.h>   
  11. #include <netinet/in.h>   
  12. #include <sys/socket.h>   
  13. #include <sys/time.h>  
  14. typedef int SOCKET;  
  15. #define MAXBUFSIZE 1024  
  16. #define NLISTEN 1024  
  17. #define isvalidsock(s)  ( ( s ) > 0 )  
  18. void set_address( char *hname, char *sname,struct sockaddr_in *sap, char *protocol )  
  19. {  
  20.     struct servent *sp;  
  21.     struct hostent *hp;  
  22.     char *endptr;  
  23.     short port;  
  24.   
  25.     bzero( sap, sizeof( *sap ) );  
  26.     sap->sin_family = AF_INET;  
  27.     if ( hname != NULL )  
  28.     {  
  29.         if ( !inet_aton( hname, &sap->sin_addr ) )  
  30.         {  
  31.             hp = gethostbyname( hname );  
  32.             if ( hp == NULL )  
  33.                 error( 1, 0, "unknown host: %s/n", hname );  
  34.             sap->sin_addr = *( struct in_addr * )hp->h_addr;  
  35.         }  
  36.     }  
  37.     else  
  38.         sap->sin_addr.s_addr = htonl( INADDR_ANY );  
  39.     port = strtol( sname, &endptr, 0 );  
  40.     if ( *endptr == '/0' )  
  41.         sap->sin_port = htons( port );  
  42.     else  
  43.     {  
  44.         sp = getservbyname( sname, protocol );  
  45.         if ( sp == NULL )  
  46.             error( 1, 0, "unknown service: %s/n", sname );  
  47.         sap->sin_port = sp->s_port;  
  48.     }  
  49. }  
  50.   
  51. /* tcp_client - set up for a TCP client */  
  52. SOCKET tcp_client( char *hname, char *sname )  
  53. {  
  54.     struct sockaddr_in peer;  
  55.     SOCKET s;  
  56.   
  57.     set_address( hname, sname, &peer, "tcp" );  
  58.     s = socket( AF_INET, SOCK_STREAM, 0 );  
  59.     if ( !isvalidsock( s ) )  
  60.         error( 1, errno, "socket call failed" );  
  61.   
  62.     if ( connect( s, ( struct sockaddr * )&peer,  
  63.          sizeof( peer ) ) )  
  64.         error( 1, errno, "connect failed" );  
  65.   
  66.     return s;  
  67. }  
  68.   
  69.   
  70. int main(int argc,char**argv)  
  71. {  
  72.    SOCKET s;  
  73.    s = tcp_client(NULL,"5000");  
  74.    char buf[100] = {""};  
  75.    recv(s,buf,100,0);  
  76.    printf("%s/n",buf);  
  77.    printf("please input data(quit exit):");  
  78.    while(fgets(buf,100,stdin) != NULL)  
  79.    {  
  80.         if(strcmp(buf,"quit") == 0)  
  81.             break;  
  82.         send(s,buf,strlen(buf),0);  
  83.         recv(s,buf,100,0);  
  84.         printf("echo data:%s/n",buf);  
  85.         printf("please input data(quit exit):");  
  86.    }  
  87.      
  88. }  

通过: gcc selectcli.c -o selectcli 得到客户端执行程序.

  在上面的测试例子中,程序只是简单演示了如何使用select来轮询可读、可写操作的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值