Chinaunix首页 | 论坛 | 博客
  • 博客访问: 581529
  • 博文数量: 104
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1559
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-21 00:58
个人简介

锻炼精神,首先要锻炼肉体

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: C/C++

2015-03-27 14:59:34

在学习了Client 端常用的 socket , connect 和 Server 端常用的 socket bind listen accept
之后,打算写一个Client 端向 Server 发送连接请求的完整程序。

收发消息的 client/server 端可以分为阻塞方式和非阻塞方式,
这两种方式下,为了使得运行结果清晰可见,我们在这里做这样的约定

1.如果 server 端接收消息的方式是阻塞的话,那么首先启动 server端的程序代码,
待到 server 端因为没有接到任何的来自于 client 的请求信息而执行 accept 方法时处于等待状态。
此时再来启动 client 端的代码

2. 如果 server 端接收消息的方式是非阻塞的话,那么在 client 端中以 connect 方法为循环变量,
直到 connect 发送的连接请求得到 server端的回复信息之后,才会是循环结束,否则一直执行循环,
不断的向 server 端发送请求连接的消息。


示例代码1 : 阻塞方式

编译代码命令
g++ clientTest.cpp -o client
g++ serverTest.cpp -o server

// client 端代码

点击(此处)折叠或打开

  1. // clientTest.cpp

  2. #include <stdio.h> // perror
  3. #include <string.h> // memset

  4. #include <sys/types.h> // AF_INET
  5. #include <sys/socket.h> // socket
  6. #include <netinet/in.h> // sockaddr_in
  7. #include <arpa/inet.h> // inet_aton
  8. #include <unistd.h> // unix standard library


  9. #define SERVER_PORT 3699

  10. #define SERVER_IP "10.0.2.15"


  11. int getSocketDone ()
  12. {
  13.   int ret = socket(AF_INET, SOCK_STREAM , 0) ;
  14.   if ( ret < 0 )
  15.     perror ("getSocketDone failed") ;
  16.   return ret ;
  17. }

  18. int getConnectDone ( int sock_fd )
  19. {
  20.   int ret ;
  21.   struct sockaddr_in serv_addr ;
  22.   memset ( &serv_addr , 0 , sizeof( struct sockaddr_in ) ) ;
  23.  
  24.   serv_addr.sin_family = AF_INET ;
  25.   serv_addr.sin_port = htons(SERVER_PORT) ;
  26.   
  27.   ret = inet_aton (SERVER_IP , &serv_addr.sin_addr) ;
  28.   if ( ret < 0 )
  29.   {
  30.      perror ("inet_aton failed ") ;
  31.      return ret ;
  32.   }

  33.   ret = connect (sock_fd , (struct sockaddr *)(&serv_addr) , sizeof( struct sockaddr_in )) ;

  34.   if ( ret < 0 )
  35.     perror ("getConnectDone failed ") ;
  36.  
  37.   return ret ;
  38. }


  39. int main ( int c , char ** v )
  40. {
  41.   int sock_fd , ret ;
  42.   
  43.   sock_fd = getSocketDone () ;
  44.   
  45.   if (sock_fd > 0 )
  46.     printf(" client getSocketDone success sock_fd = %d \n" , sock_fd);
  47.   else
  48.     goto error ;
  49.   
  50.   if ( !getConnectDone ( sock_fd ) )
  51.   {
  52.      printf (" client getConnectDone success \n") ;
  53.      goto success ;
  54.   }
  55.   else
  56.     goto error ;
  57.   
  58.   error :
  59.      perror ("failed ") ;
  60.      goto success ;
  61.   success :
  62.     return 0 ;
  63. }

// server 端代码

点击(此处)折叠或打开

  1. //serverTest.cpp

  2. #include <stdio.h>

  3. #include <string.h> // memset

  4. #include <sys/types.h> // AF_INET , AF_INET6 , SOCK_STREAM , SOCK_DGRAM

  5. #include <sys/socket.h> // socket , bind , listen , accept

  6. #include <netinet/in.h> // sockaddr_in

  7. #include <unistd.h> // unix standard library

  8. #include <fcntl.h> // fcntl , set accept non-block mode


  9. #define SERVER_PORT 3699

  10. #define MAX_LISTEN_QUEUE_LENGTH 10


  11. int getSocketDone ()

  12. {

  13.   int ret = socket (AF_INET, SOCK_STREAM , 0 ) ;

  14.   if ( ret < 0 )

  15.     perror ("getSocketDone failed") ;

  16.   

  17.   return ret ;

  18. }


  19. int getBindDone ( int sock_fd )

  20. {

  21.   struct sockaddr_in serv_addr ;

  22.   int ret ;

  23.   
  24.   memset ( &serv_addr , 0 , sizeof( struct sockaddr_in )) ;

  25.   serv_addr.sin_family = AF_INET ;

  26.   serv_addr.sin_port = htons (SERVER_PORT) ;

  27.   serv_addr.sin_addr.s_addr = htonl ( INADDR_ANY ) ;

  28.  

  29.   ret = bind (sock_fd , (struct sockaddr *)(&serv_addr) , sizeof( struct sockaddr_in ) ) ;

  30.   
  31.   if ( ret < 0 )

  32.     perror ("getBindDone failed");

  33.   return ret ;

  34. }


  35. int getListenDone ( int sock_fd )

  36. {

  37.   int ret = listen ( sock_fd , MAX_LISTEN_QUEUE_LENGTH ) ;

  38.   if ( ret < 0 )

  39.     perror ("getListenDone failed ") ;

  40.   return ret ;

  41. }


  42. int setNonBlock ( int *sock_fd )

  43. {

  44.   int ret = fcntl (*sock_fd , F_SETFL , O_NONBLOCK) ;

  45.   if ( ret < 0 )

  46.     perror ("setNonBlock failed") ;

  47.   return ret ;

  48. }


  49. int getAcceptDone ( int sock_fd_queue , struct sockaddr_in *client_addr , int *client_len )

  50. {

  51.    int sock_fd_conn ;  

  52.    *client_len = sizeof( struct sockaddr_in) ;

  53.    sock_fd_conn = accept (sock_fd_queue , (struct sockaddr *)client_addr ,(socklen_t*) client_len) ;

  54.    if ( sock_fd_conn < 0 )

  55.       perror ("getAcceptDone failed ") ;

  56.    return sock_fd_conn ;

  57. }

  58. // this is the blocking mode ,first get server start

  59. // then execute the client


  60. int main ( int c , char ** v )

  61. {

  62.     int sock_fd_queue, sock_fd_conn , ret ;

  63.     int client_len ;

  64.     struct sockaddr_in client_addr ;

  65.     sock_fd_queue = getSocketDone () ;

  66.     if ( sock_fd_queue > 0 )

  67.        printf ("getSocketDone success \n") ;

  68.     else

  69.      goto error ;

  70.     
  71.     if ( !getBindDone ( sock_fd_queue ) )

  72.        printf ("getBindDone success \n") ;

  73.     else

  74.     goto error ;

  75.    if ( !getListenDone ( sock_fd_queue ))

  76.     printf ("getListenDone success \n") ;

  77.    else

  78.     goto error ;


  79.    if ( ( sock_fd_conn = getAcceptDone (sock_fd_queue , &(client_addr) , &(client_len) ) ) > 0 )

  80.    {

  81.       printf ("getAcceptDone success , new socket connect fd is %d\n" , sock_fd_conn ) ;

  82.       printf ("peer port : %s" , ntohs(client_addr.sin_port)) ;

  83.       goto success ;

  84.    }

  85.   else

  86.      goto error ;

  87. error :

  88.    perror ("method failed") ;

  89.    goto success ;

  90. success :    

  91.    return 0 ;    

  92. }

代码运行结果
首先运行 server , 然后打开一个新的命令终端窗口运行 client

./server 控制台打印信息
etSocketDone success 
getBindDone success 
getListenDone success 
getAcceptDone success , new socket connect fd is 4
Segmentation fault (core dumped)

./client 显示信息如下
 client getSocketDone success sock_fd = 3 
 client getConnectDone success 



示例代码2 : server 端以阻塞的方式来接收来自 client 端的消息

大部分代码和示例代码1 相同,红色代码除外

// Client 端代码 (首先运行 client 端代码)

点击(此处)折叠或打开

  1. // clientTest2.cpp
  2. // non-blocking working mode

  3. #include <stdio.h> // perror
  4. #include <string.h> // memset

  5. #include <sys/types.h> // AF_INET
  6. #include <sys/socket.h> // socket
  7. #include <netinet/in.h> // sockaddr_in
  8. #include <arpa/inet.h> // inet_aton
  9. #include <unistd.h> // unix standard library


  10. #define SERVER_PORT 3699

  11. #define SERVER_IP "10.0.2.15"


  12. int getSocketDone ()
  13. {
  14.   int ret = socket(AF_INET, SOCK_STREAM , 0) ;
  15.   if ( ret < 0 )
  16.     perror ("getSocketDone failed") ;
  17.   return ret ;
  18. }

  19. int getConnectDone ( int sock_fd )
  20. {
  21.   int ret ;
  22.   struct sockaddr_in serv_addr ;
  23.   memset ( &serv_addr , 0 , sizeof( struct sockaddr_in ) ) ;
  24.  
  25.   serv_addr.sin_family = AF_INET ;
  26.   serv_addr.sin_port = htons(SERVER_PORT) ;
  27.   
  28.   ret = inet_aton (SERVER_IP , &serv_addr.sin_addr) ;
  29.   if ( ret < 0 )
  30.   {
  31.      perror ("inet_aton failed ") ;
  32.      return ret ;
  33.   }

  34.   ret = connect (sock_fd , (struct sockaddr *)(&serv_addr) , sizeof( struct sockaddr_in )) ;

  35.   if ( ret < 0 )
  36.     perror ("getConnectDone failed ") ;
  37.  
  38.   return ret ;
  39. }


  40. int main ( int c , char ** v )
  41. {
  42.   int sock_fd , ret ;
  43.   
  44.   sock_fd = getSocketDone () ;
  45.   
  46.   if (sock_fd > 0 )
  47.     printf(" client getSocketDone success sock_fd = %d \n" , sock_fd);
  48.   else
  49.     goto error ;
  50.   
  51.   while ( getConnectDone ( sock_fd ) < 0 )
  52.   {
  53.      printf ("waiting for server set up\n ") ;
  54.   }
  55.  
  56.   printf ("success send connect request to server \n") ;
  57.   goto success ;

  58.   error :
  59.      perror ("failed ") ;
  60.      goto success ;
  61.   success :
  62.     return 0 ;
  63. }
// Server 端代码 (然后打开一个空闲的命令终端,运行 Server 端代码)

点击(此处)折叠或打开

  1. //serverTest2.cpp
  2. // non-block

  3. #include <stdio.h>
  4. #include <string.h> // memset

  5. #include <sys/types.h> // AF_INET , AF_INET6 , SOCK_STREAM , SOCK_DGRAM
  6. #include <sys/socket.h> // socket , bind , listen , accept
  7. #include <netinet/in.h> // sockaddr_in
  8. #include <unistd.h> // unix standard library
  9. #include <fcntl.h> // fcntl , set accept non-block mode


  10. #define SERVER_PORT 3699
  11. #define MAX_LISTEN_QUEUE_LENGTH 10


  12. int getSocketDone ()
  13. {
  14.   int ret = socket (AF_INET, SOCK_STREAM , 0 ) ;
  15.   if ( ret < 0 )
  16.     perror ("getSocketDone failed") ;
  17.   
  18.   return ret ;
  19. }

  20. int getBindDone ( int sock_fd )
  21. {
  22.   struct sockaddr_in serv_addr ;
  23.   int ret ;
  24.   
  25.   memset ( &serv_addr , 0 , sizeof( struct sockaddr_in )) ;
  26.   serv_addr.sin_family = AF_INET ;
  27.   serv_addr.sin_port = htons (SERVER_PORT) ;
  28.   serv_addr.sin_addr.s_addr = htonl ( INADDR_ANY ) ;
  29.  
  30.   ret = bind (sock_fd , (struct sockaddr *)(&serv_addr) , sizeof( struct sockaddr_in ) ) ;
  31.   
  32.   if ( ret < 0 )
  33.     perror ("getBindDone failed");
  34.  
  35.   return ret ;
  36. }

  37. int getListenDone ( int sock_fd )
  38. {
  39.   int ret = listen ( sock_fd , MAX_LISTEN_QUEUE_LENGTH ) ;
  40.  
  41.   if ( ret < 0 )
  42.     perror ("getListenDone failed ") ;
  43.    
  44.   return ret ;
  45. }

  46. int setNonBlock ( int *sock_fd )
  47. {
  48.   int ret = fcntl (*sock_fd , F_SETFL , O_NONBLOCK) ;
  49.   if ( ret < 0 )
  50.     perror ("setNonBlock failed") ;

  51.   return ret ;
  52. }

  53. int getAcceptDone ( int sock_fd_queue , struct sockaddr_in *client_addr , int *client_len )
  54. {
  55.    int sock_fd_conn ;
  56.   
  57.    *client_len = sizeof( struct sockaddr_in) ;
  58.   
  59.    sock_fd_conn = accept (sock_fd_queue , (struct sockaddr *)client_addr ,(socklen_t*) client_len) ;

  60.    if ( sock_fd_conn < 0 )
  61.       perror ("getAcceptDone failed ") ;
  62.    return sock_fd_conn ;
  63. }

  64. // this is the blocking mode ,first get server start
  65. // then execute the client

  66. int main ( int c , char ** v )
  67. {
  68.     int sock_fd_queue, sock_fd_conn , ret ;
  69.     int client_len ;
  70.     struct sockaddr_in client_addr ;
  71.   

  72.     sock_fd_queue = getSocketDone () ;
  73.     
  74.     if ( sock_fd_queue > 0 )
  75.        printf ("getSocketDone success \n") ;
  76.     else
  77.      goto error ;
  78.     
  79.     if ( !getBindDone ( sock_fd_queue ) )
  80.        printf ("getBindDone success \n") ;
  81.     else
  82.     goto error ;
  83.      
  84.    if ( !getListenDone ( sock_fd_queue ))
  85.     printf ("getListenDone success \n") ;
  86.    else
  87.     goto error ;

  88.    // set non block mode
  89.     if ( !setNonBlock (&sock_fd_queue) )
  90.        printf ("set server accepting mode non-blocking \n") ;
  91.     else
  92.        goto error ;

  93.    while ( 1 )
  94.    {
  95.       sock_fd_conn = getAcceptDone (sock_fd_queue , &(client_addr) , &(client_len) ) ;
  96.       if ( sock_fd_conn > 0 ) break ;
  97.    }
  98.    
  99.   printf ("get new connect request sock_fd is %d \n" , sock_fd_conn) ;
  100.   goto success ;
  101.  
  102. error :
  103.    perror ("method failed") ;
  104.    goto success ;
  105. success :    
  106.    return 0 ;    
  107. }
client端执行结果
.....
getConnectDone failed : Connection refused
 waiting for server set up
.......
......
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
getConnectDone failed : Connection refused
 waiting for server set up
 success send connect request to server 

server 端执行结果:

getSocketDone success 
getBindDone success 
getListenDone success 
set server accepting mode non-blocking 
getAcceptDone failed : Resource temporarily unavailable
get new connect request sock_fd is 4 

阅读(2720) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~