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

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

文章分类

全部博文(104)

文章存档

2018年(1)

2016年(1)

2015年(101)

2014年(1)

我的朋友

分类: C/C++

2015-04-27 07:34:42

在前几篇的博客中简单的介绍了一下 BSON 的使用方法,那么在这片文章中将介绍一下网络编程中,
如何使用 BSON 来在服务器和客户端
收发消息结构。
本篇文章中的示例代码是基于前一篇文章中"[c++, linux]网络编程之 poll 的使用方法" 所编写的服务器端和客户端代码实现的。

代码结构
message_sender/
                 |-------------/utils/
                                     |------ message.h
                 |-------------/client/
                                      |----- client.cpp
                                      |----- build.sh
                                      |----- Makefile.am
                                      |----- configure.in
                 |------------/server/                   
                                      |----- server.cpp
                                      |----- build.sh
                                      |----- Makefile.am
                                      |----- configure.in             
示例代码
utils/message.h

点击(此处)折叠或打开

  1. #ifndef MESSAGE_H
  2. #define MESSAGE_H

  3. typedef struct msg_header
  4. {
  5.   int len ;
  6.   
  7.   msg_header() : len (0)
  8.   {}

  9. } header_t;

  10. typedef struct msg
  11. {
  12.   header_t header ;
  13.   char data[0] ;

  14. } message_t;


  15. #endif // message.h
Client
1. build.sh

点击(此处)折叠或打开

  1. #!/bin/sh

  2. autoscan
  3. aclocal
  4. autoconf
  5. autoheader #after autoheader , create a Makefile.am then continue execute follow command
  6. automake --add-missing
  7. ./configure CXXFLAGS= CFLAGS=
  8. make
2.configure.in

点击(此处)折叠或打开

  1. # -*- Autoconf -*-
  2. # Process this file with autoconf to produce a configure script.

  3. AC_INIT(message_sender_client)
  4. AC_CONFIG_SRCDIR([client.cpp])
  5. AC_CONFIG_HEADERS([config.h])

  6. AM_INIT_AUTOMAKE(message_sender_client, 1.0)


  7. # Checks for programs.
  8. AC_PROG_CXX
  9. AC_PROG_CC

  10. #add by Aimer , cause method use realloc
  11. AC_FUNC_REALLOC

  12. # Checks for header files.
  13. AC_CHECK_HEADERS([arpa/inet.h netinet/in.h strings.h sys/socket.h unistd.h])

  14. # Checks for typedefs, structures, and compiler characteristics.
  15. AC_TYPE_SSIZE_T

  16. # Checks for library functions.
  17. AC_CHECK_FUNCS([bzero socket])

  18. AC_OUTPUT(Makefile)
3.Makefile.am

点击(此处)折叠或打开

  1. AUTOMAKE_OPTIONS=foreign
  2. bin_PROGRAMS=message_sender_client
  3. #define short names for bson path and boost path
  4. BSON_PATH=/unixC/Bson/bson/src
  5. BOOST_PATH=/unixC/Boost/boost_1_58_0
  6. message_sender_client_SOURCES=\
  7. client.cpp \
  8. $(BSON_PATH)/bsonobj.cpp $(BSON_PATH)/util/json.cpp \
  9. $(BSON_PATH)/oid.cpp $(BSON_PATH)/lib/base64.cpp \
  10. $(BSON_PATH)/lib/md5.cpp $(BSON_PATH)/lib/nonce.cpp
  11. message_sender_client_CXXFLAGS=\
  12. -I$(BOOST_PATH) -I$(BSON_PATH) \
  13. -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0
  14. message_sender_client_LDADD=\
  15. -lpthread -lm -lboost_system -lboost_thread \
  16. -lboost_thread -lboost_program_options -lrt
  17. message_sender_client_LDFLAGS=\
  18. -fPIC -rdynamic -L$(BOOST_PATH)/stage/lib -pthread
4.client.cpp

点击(此处)折叠或打开

  1. #include <cstdio> // perror
  2. #include <cstring> // string
  3. #include <strings.h> // memset
  4. #include <iostream>
  5. #include <sys/types.h> // AF_INET, SOCK_STREAM
  6. #include <sys/socket.h> // socket , connect
  7. #include <arpa/inet.h> // inet_aton
  8. #include <netinet/in.h>
  9. #include <unistd.h>

  10. #include <bson.h> // BSONObj , BSONObjBuilder

  11. #include "../utils/message.h" // struct message_t

  12. #define SERVER_PORT 1027
  13. #define SERVER_IP "10.0.2.15"
  14. #define MAXLINE 1024*2

  15. using namespace std ;
  16. using namespace bson ;

  17. // add method buildMessage here
  18. /**
  19. method :
  20.  int buildMessage ( char **ppBuffer[out], int *pBufferSize[out], BSONObj *obj[in] )
  21.  return :
  22.         0 if success building a message
  23.         -1 if failed building a message
  24. */

  25. int buildMessage ( char **ppBuffer , int *pBufferSize , BSONObj *obj )
  26. {
  27.    message_t *pMessage = NULL ;
  28.    int size = sizeof(message_t) ;

  29.    if ( obj != NULL )
  30.        size += obj->objsize() ;
  31.    
  32.    if ( size > *pBufferSize )
  33.    {
  34.     *ppBuffer = (char*)realloc(*ppBuffer , size*sizeof(char)) ;
  35.          *pBufferSize = size ;
  36.         
  37.          if ( *ppBuffer == NULL )
  38.      {
  39.         perror ("failed to realloc space for ppBuffer") ;
  40.         return -1 ;
  41.          }
  42.    }
  43.   
  44.   pMessage = (message_t*)(*ppBuffer) ;
  45.   pMessage->header.len = size ;
  46.  
  47.   if ( obj != NULL )
  48.   {
  49.     memcpy (&pMessage->data[0] , obj->objdata() , obj->objsize() ) ;
  50.   }
  51.  
  52.   return 0 ;
  53. }


  54. int main ( int argc , char **argv )
  55. {
  56.    char buf [MAXLINE] ;
  57.    ssize_t n ; // message content length
  58.    struct sockaddr_in server_addr ;
  59.    int connfd ;
  60.    int ret ;
  61.    string msg ;
  62.     
  63.    connfd = socket (AF_INET , SOCK_STREAM , 0 ) ;
  64.    bzero (&server_addr , sizeof(struct sockaddr_in)) ;
  65.   
  66.    server_addr.sin_family = AF_INET ;
  67.    server_addr.sin_port = htons (SERVER_PORT) ;
  68.    inet_aton (SERVER_IP , &server_addr.sin_addr ) ;
  69.    
  70.    ret = connect ( connfd , (struct sockaddr*)&server_addr , sizeof(struct sockaddr_in) ) ;    
  71.   

  72.  if ( ret < 0 )
  73.   {
  74.     perror ("failed connect") ;
  75.     return -1;
  76.   }
  77.   
  78.   cout << "input message "<< endl ;
  79.   cin >> msg ;
  80.  
  81.   BSONObjBuilder builder ;
  82.   
  83.   builder.append ("message data", msg.c_str ()) ;

  84.   BSONObj obj = builder.obj() ;
  85.   
  86.   char *pBuffer = NULL ;
  87.   int pBufferSize = 0 ;
  88.   
  89.   cout << obj.toString() << endl ;

  90.   cout << "-------- /test build message/ ------------"<<endl ;
  91.   
  92.   buildMessage (&pBuffer , &pBufferSize , &obj) ;

  93. // pBuffer content can not be seen on console
  94. // cout << " here is the pBuffer content \n "<< pBuffer << endl ;
  95.   cout <<"message size " << pBufferSize << endl ;
  96.   cout << "message data size " << obj.objsize() << endl ;
  97.   cout << "message header size " << pBufferSize - obj.objsize() << endl ;
  98.   
  99.   write (connfd , pBuffer , pBufferSize ) ;
  100.     

  101.  return 0 ;
  102. }



Server

1.build.sh

点击(此处)折叠或打开

  1. #!/bin/sh
  2. autoscan
  3. aclocal
  4. autoconf
  5. autoheader
  6. automake --add-missing
  7. ./configure CXXFLAGS= CFLAGS=
  8. make
2.configure.in

点击(此处)折叠或打开

  1. # -*- Autoconf -*-
  2. # Process this file with autoconf to produce a configure script.
  3. AC_INIT(message_sender_server)
  4. AC_USE_SYSTEM_EXTENSIONS # we will use bson and boost
  5. AM_INIT_AUTOMAKE(message_sender_server,1.0)
  6. AC_CONFIG_SRCDIR([server.cpp])
  7. AC_CONFIG_HEADERS([config.h])
  8. # Checks for programs.
  9. AC_PROG_CXX
  10. AC_PROG_CC
  11. # Checks for libraries.
  12. # Checks for header files.
  13. AC_CHECK_HEADERS([limits.h netdb.h netinet/in.h strings.h sys/socket.h unistd.h])
  14. # Checks for typedefs, structures, and compiler characteristics.
  15. AC_TYPE_SSIZE_T
  16. # Checks for library functions.
  17. AC_CHECK_FUNCS([bzero socket])
  18. AC_OUTPUT(Makefile)
3.Makefile.am

点击(此处)折叠或打开

  1. AUTOMAKE_OPTIONS=foreign
  2. bin_PROGRAMS=message_sender_server
  3. BSON_PATH=/unixC/Bson/bson/src
  4. BOOST_PATH=/unixC/Boost/boost_1_58_0
  5. message_sender_server_SOURCES=\
  6. server.cpp \
  7. $(BSON_PATH)/bsonobj.cpp $(BSON_PATH)/util/json.cpp \
  8. $(BSON_PATH)/oid.cpp $(BSON_PATH)/lib/base64.cpp \
  9. $(BSON_PATH)/lib/md5.cpp $(BSON_PATH)/lib/nonce.cpp
  10. message_sender_server_CXXFLAGS=\
  11. -I$(BOOST_PATH) -I$(BSON_PATH) -D_FILE_OFFSET_BITS=64 \
  12. -ggdb -Wall -O0
  13. message_sender_server_LDADD=\
  14. -lpthread -lm -lboost_system -lboost_thread \
  15. -lboost_thread -lboost_program_options -lrt
  16. message_sender_server_LDFLAGS=\
  17. -fPIC -rdynamic -L$(BOOST_PATH)/stage/lib -pthread
4.server.cpp

点击(此处)折叠或打开

  1. #include <cstdio>
  2. #include <limits.h>
  3. #include <sys/types.h>     // socket , bind , accept
  4. #include <sys/socket.h>     // socket , bind , socklen_t , accept
  5. #include <poll.h>     // poll, struct pollfd
  6. #include <netdb.h>     // socklen_t
  7. #include <netinet/in.h>     // struct sockaddr_in , sockaddr
  8. #include <errno.h>         // errno
  9. #include <unistd.h> // read, write
  10. #include <strings.h>        // bzero
  11. #include <iostream> // cout , endl , cin

  12. #include <bson.h> // BSONObj
  13. #include "../utils/message.h" // struct message_t

  14. #define MAXLINE     1024*2
  15. #define OPEN_MAX     1024
  16. #define SERVER_PORT     1027
  17. #define INFTIM        1024

  18. using namespace std ;
  19. using namespace bson ;

  20. //add method parseMessage
  21. /**
  22. method :
  23.     this method is used to extract message's data
  24.     from char *pBuffer , into BSONObj this object
  25.     int parseMessage( char *pBuffer [in], BSONObj &msgData [out])
  26.     return:
  27.     0 : success extracting message data into BSONObj
  28.         -1: failed extracting message data into BSONObj
  29.     
  30.    [in] : means this parameter is pass-in-value parameter
  31.    [out] : means this parameter is value-result which can
  32.      also be recognized as the return value of the method
  33. */

  34. int parseMessage ( char *pBuffer, BSONObj &msgData )
  35. {
  36.   if ( pBuffer == NULL )
  37.   {
  38.     perror ("message is invalid ") ;
  39.     return -1 ;
  40.   }

  41.   message_t *pMessage = (message_t*)(pBuffer) ;
  42.  
  43.   if ( pMessage->header.len < sizeof(message_t) )
  44.   {
  45.     perror ("message content is invalid ") ;
  46.     return -1 ;
  47.   }

  48.  // cout << pMessage->header.len << endl ;
  49. // cout << &pMessage->data[0] << endl ;

  50. // BSONObjBuilder builder ;
  51. // builder.append ("", &(pMessage->data[0])) ;

  52.   msgData = BSONObj(&pMessage->data[0]) ;

  53.   
  54.   return 0 ;
  55. }


  56. int main ( int argc , char ** argv )
  57. {
  58.     int i , maxi , listenfd , connfd , sockfd ;
  59.     int nready ;
  60.     ssize_t n ;
  61.     char buf[MAXLINE] ;
  62.     socklen_t client_len ;    
  63.     struct pollfd client[OPEN_MAX] ;
  64.     struct sockaddr_in client_addr , server_addr ;
  65.     
  66.     listenfd = socket ( AF_INET , SOCK_STREAM , 0 ) ;
  67.     bzero ( &server_addr , sizeof(struct sockaddr_in)) ;
  68.     
  69.     server_addr.sin_family = AF_INET ;
  70.     server_addr.sin_addr.s_addr = htonl (INADDR_ANY) ;
  71.     server_addr.sin_port = htons ( SERVER_PORT ) ;
  72.     
  73.     bind (listenfd , (struct sockaddr*)&server_addr ,
  74.             sizeof(struct sockaddr_in) ) ;
  75.     
  76.     listen ( listenfd , 10 ) ;
  77.     
  78.     client[0].fd = listenfd ;
  79.     client[0].events = POLLRDNORM ; // poll read normal
  80.     
  81.     for ( i = 1 ; i < OPEN_MAX ; i++ )
  82.     {
  83.      client[i].fd = -1;
  84.     }
  85.     
  86.     maxi = 0 ;
  87.     
  88.     for ( ; ; )
  89.     {
  90.         nready = poll (client , maxi+1 , INFTIM) ;
  91.     
  92.      if ( client[0].revents & POLLRDNORM )
  93.      {
  94.          // this means new client connection request come
  95.          client_len = sizeof( struct sockaddr_in ) ;
  96.          connfd = accept ( listenfd , (struct sockaddr*)&client_addr ,
  97.             &client_len ) ;
  98.         
  99.          // updates maxi, and check if i out of limition of OPEN_MAX
  100.          for ( i = 1 ; i < OPEN_MAX ; i++ )
  101.          {
  102.             if ( client[i].fd < 0 )
  103.             {
  104.              client[i].fd = connfd ;
  105.              break ;
  106.             }    
  107.          } // for
  108.         
  109.          if ( i == OPEN_MAX )
  110.          {
  111.             perror ("too many client requests ") ;
  112.             return -1 ;
  113.          }
  114.         
  115.          client[i].events = POLLRDNORM ;
  116.         
  117.                   if ( i > maxi )
  118.          maxi = i ;
  119.             
  120.          if ( --nready <= 0 )
  121.             continue ;
  122.      } // if
  123.         
  124.         for ( i = 1 ; i <= maxi ; i++ )
  125.         {
  126.          if ( ( sockfd = client[i].fd ) < 0 )
  127.             continue ; // continue the sub for cycle
  128.             
  129.          if ( client[i].revents & (POLLRDNORM | POLLERR) )
  130.          {
  131.                    if ( ( n = read(sockfd , buf , MAXLINE)) < 0 )
  132.              {
  133.                 // read n < 0 , it must some error happen
  134.                  // if client reset connection , release client[i].fd
  135.                 // else return error code
  136.              if ( errno == ECONNRESET )
  137.              {
  138.                     // this means client reset connection
  139.                     close (sockfd) ;
  140.                     client[i].fd = -1 ;
  141.                 }
  142.                 else
  143.                 {
  144.                     perror ("error when server read from client") ;
  145.                     return -1 ;
  146.                 }

  147.              }
  148.              else if ( n == 0 )
  149.              {
  150.                 // this means client close connection
  151.                 close (sockfd) ;
  152.                 client[i].fd = -1 ;
  153.              }
  154.              else
  155.              {
  156.         
  157.                 //cout << "n = " << n << endl ;
  158.                 
  159.                 BSONObj msgData ;
  160.                 
  161.                 parseMessage (buf , msgData) ;
  162.                 cout << msgData.toString() << endl ;

  163.                 // n > 0 , server read something from client
  164.      // cout << "receive message len " << msgData.objsize() <<endl ;
  165.             }

  166.          } // if POLLRDNORM | POLLERROR
  167.     
  168.         }// for
  169.         
  170.     } // main cycle
  171.     
  172.     return 0 ;
  173. }

end

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