C++数据引擎开发第二周记录

来源:互联网 发布:淘宝优站合作哪些网站 编辑:程序博客网 时间:2024/06/10 17:57
//第一步:在core.hpp里面定义需要的头文件、全局变量等:目录文件:/emeralddb/src/include/core.hpp/******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************///宏定义,避免重复定义#ifndef CORE_HPP__#define CORE_HPP__//下面是常用的标准头文件#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <linux/limits.h>#include <sys/time.h>#include <time.h>#include <stdarg.h>#include <unistd.h>#include <syscall.h>#include <fcntl.h>#include <sys/stat.h>#include <errno.h>#include <signal.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <netinet/tcp.h>#include <sys/mman.h>//下面是常用的c++头文件#include <string>#include <map>#include <set>#include <vector>#include <iostream>//下面是全局变量,如换行符、操作中的各种权限、错误码定义等#define OSS_MAX_PATHSIZE  PATH_MAX#define OSS_FILE_SEP_STR  "/"#define OSS_FILE_SEP_CHAR *((const char*)OSS_FILE_SEP_STR)[0]#define OSS_NEWLINE       "\n"// error code list#define EDB_OK                                           0#define EDB_IO                                          -1#define EDB_INVALIDARG                                  -2#define EDB_PERM                                        -3#define EDB_OOM                                         -4#define EDB_SYS                                         -5#define EDB_PMD_HELP_ONLY                               -6#define EDB_PMD_FORCE_SYSTEM_EDU                        -7#define EDB_TIMEOUT                                     -8#define EDB_QUIESCED                                    -9#define EDB_EDU_INVAL_STATUS                            -10#define EDB_NETWORK                                     -11#define EDB_NETWORK_CLOSE                               -12#define EDB_APP_FORCED                                  -13#define EDB_IXM_ID_EXIST                                -14#define EDB_HEADER_INVALID                              -15#define EDB_IXM_ID_NOT_EXIST                            -16#define EDB_NO_ID                                       -17#endif//第二步:定义ossSocket.hpp头文件,声明socket操作需要的成员变量和成员函数,目录文件:/emeralddb/src/include/ossSocket.hpp/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#ifndef OSSNETWORK_HPP_#define OSSNETWORK_HPP_#include "core.hpp"#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <netdb.h>#include <netinet/tcp.h>#include <string.h>#define SOCKET_GETLASTERROR errno// by default 10ms timeout#define OSS_SOCKET_DFT_TIMEOUT 10000// max hostname#define OSS_MAX_HOSTNAME NI_MAXHOST#define OSS_MAX_SERVICENAME NI_MAXSERVclass _ossSocket{private ://私有成员变量定义   int _fd ;   socklen_t _addressLen ;  //socket地址长度   socklen_t _peerAddressLen ;  //对方地址长度   struct sockaddr_in  _sockAddress ; //本地socket套接字   struct sockaddr_in  _peerAddress ;   //远程socket套接字   bool _init ;    //是否初始化操作   int _timeout ;   //超时时间protected://受保护成员函数方法定义   unsigned int _getPort ( sockaddr_in *addr ) ;    //根据socket地址或端口函数   int _getAddress ( sockaddr_in *addr, char *pAddress, unsigned int length ) ; //获取socket地址函数public ://公共成员函数方法定义   int setSocketLi ( int lOnOff, int linger ) ;      void setAddress(const char * pHostName, unsigned int port );   // Create a listening socket   _ossSocket();      //创建监听   _ossSocket ( unsigned int port, int timeout = 0 ) ;  //创建监听(带参)   // Create a connecting socket   _ossSocket ( const char *pHostname, unsigned int port, int timeout = 0 ) ;//创建socket连接   // Create from a existing socket   _ossSocket ( int *sock, int timeout = 0 ) ;    //根据一个已存在的socket信息创建一个socket连接   ~_ossSocket ()       //释放资源的析构函数   {      close () ;   }   int initSocket () ;      //初始化socket套接字函数   int bind_listen () ;      //绑定socket监听函数   bool isConnected () ;     //判断socket连接状态   int send ( const char *pMsg, int len,                int timeout = OSS_SOCKET_DFT_TIMEOUT,  //客户端开始发送信息                int flags = 0 ) ;   int recv ( char *pMsg, int len,                int timeout = OSS_SOCKET_DFT_TIMEOUT,  //客户端开始接收信息,如果超时时间为0,则一直等到接收len长度信息为止                int flags = 0 ) ;   int recvNF ( char *pMsg, int &len,                  int timeout = OSS_SOCKET_DFT_TIMEOUT ) ; //客户端开始接收信息函数,收到信息后立即返回   int connect () ;      //开始socket连接   void close () ;      //关闭socket连接   int accept ( int *sock, struct sockaddr *addr, socklen_t *addrlen,                  int timeout = OSS_SOCKET_DFT_TIMEOUT ) ;      //socket服务端接收客户端消息函数   int disableNagle () ;     //关闭使用tcp打包消息处理,数据库交互一般不使用,要求实时单个数据包交互处理   unsigned int getPeerPort () ;   int getPeerAddress ( char *pAddress, unsigned int length ) ;//获取对方端口   unsigned int getLocalPort () ;   int getLocalAddress ( char *pAddress, unsigned int length ) ;//获取本地端口   int setTimeout ( int seconds ) ;    //设置超时时间   static int getHostName ( char *pName, int nameLen ) ; //获取主机名   static int getPort ( const char *pServiceName, unsigned short &port ) ;//根据服务名转化为端口号,/etc/services下面有服务名和端口号匹配的所有定义};typedef class _ossSocket ossSocket ;#endif//第三步:定义ossSocket.cpp头文件,具体实现socket操作需要的成员变量和成员函数,目录文件:/emeralddb/src/oss/ossSocket.cpp/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include <stdio.h>#include "ossSocket.hpp"// Create a listening socket 创建一个socket监听_ossSocket::_ossSocket ( unsigned int port, int timeout ){   _init = false ;   _fd = 0 ;   _timeout = timeout ;   memset ( &_sockAddress, 0, sizeof(sockaddr_in) ) ; //初始化_sockAddress分配空间并清0   memset ( &_peerAddress, 0, sizeof(sockaddr_in) ) ;   _peerAddressLen = sizeof (_peerAddress) ;  //对方地址长度    _sockAddress.sin_family = AF_INET ;   //初始化本地的AF_INET属性   _sockAddress.sin_addr.s_addr = htonl ( INADDR_ANY ) ;//设置监听的来源是全部来源   _sockAddress.sin_port = htons ( port ) ;  //设置监听端口号   _addressLen = sizeof ( _sockAddress ) ;  //设置地址长度}// Create a socket 创建一个socket连接_ossSocket::_ossSocket(){   _init = false;   _timeout = 0;   _fd = 0;   memset( &_sockAddress, 0, sizeof(sockaddr_in) );   memset( &_peerAddress, 0, sizeof(sockaddr_in) );   _peerAddressLen = sizeof(_peerAddress);}// Create a connecting socket 创建一个客户端的socket套接字_ossSocket::_ossSocket ( const char *pHostname, unsigned int port, int timeout ){   struct hostent *hp ;   _init = false ;   _timeout = timeout ;   _fd = 0 ;   memset ( &_sockAddress, 0, sizeof(sockaddr_in) ) ;   memset ( &_peerAddress, 0, sizeof(sockaddr_in) ) ;   _peerAddressLen = sizeof (_peerAddress) ;   _sockAddress.sin_family = AF_INET ;   if ( (hp = gethostbyname ( pHostname )))//解析对方的机器名,如果解析成功用收到的地址,否则尝试用pHostname作为绝对地址      _sockAddress.sin_addr.s_addr = *((int *)hp->h_addr_list[0] ) ;    else      _sockAddress.sin_addr.s_addr = inet_addr ( pHostname ) ;   _sockAddress.sin_port = htons ( port ) ;   _addressLen = sizeof ( _sockAddress ) ;}// Create from a existing socket //从一个已存在的套接字构建socket_ossSocket::_ossSocket ( int *sock, int timeout ){   int rc = EDB_OK ;   _fd = *sock ;   _init = true ;   _timeout = timeout ;   _addressLen = sizeof ( _sockAddress ) ;   memset ( &_peerAddress, 0, sizeof(sockaddr_in) ) ;   _peerAddressLen = sizeof ( _peerAddress ) ;   rc = getsockname ( _fd, (sockaddr*)&_sockAddress, &_addressLen ) ;//从一个已存在的socket里面得到对方的地址   if ( rc )   {      printf ( "Failed to get sock name, error = %d",              SOCKET_GETLASTERROR ) ;      _init = false ;   }   else   {      //get peer address            rc = getpeername ( _fd, (sockaddr*)&_peerAddress, &_peerAddressLen ) ;      if ( rc )      {         printf ( "Failed to get peer name, error = %d",                 SOCKET_GETLASTERROR ) ;      }   }}int ossSocket::initSocket (){   int rc = EDB_OK ;   if ( _init )   {      goto done ;   }   memset ( &_peerAddress, 0, sizeof(sockaddr_in) ) ;   _peerAddressLen = sizeof ( _peerAddress ) ;   _fd = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ;//创建一个新的socket套接字   if ( -1 == _fd )   {      printf ( "Failed to initialize socket, error = %d",              SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }   _init = true ;   // settimeout should always return EDB_OK   setTimeout ( _timeout ) ;done :   return rc ;error:   goto done ;}int ossSocket::setSocketLi ( int lOnOff, int linger ){   int rc = EDB_OK ;   struct linger _linger ;   _linger.l_onoff = lOnOff ;   _linger.l_linger = linger ;   rc = setsockopt ( _fd, SOL_SOCKET, SO_LINGER,                     (const char*)&_linger, sizeof (_linger) ) ;//设置socket属性   return rc ;}void ossSocket::setAddress(const char* pHostname, unsigned int port ){    struct hostent *hp ;    memset ( &_sockAddress, 0, sizeof(sockaddr_in) ) ;    memset ( &_peerAddress, 0, sizeof(sockaddr_in) ) ;    _peerAddressLen = sizeof (_peerAddress) ;    _sockAddress.sin_family = AF_INET ;    if ( (hp = gethostbyname ( pHostname )))//解析域名       _sockAddress.sin_addr.s_addr = *((int *)hp->h_addr_list[0] ) ;    else       _sockAddress.sin_addr.s_addr = inet_addr ( pHostname ) ;    _sockAddress.sin_port = htons ( port ) ;    _addressLen = sizeof ( _sockAddress ) ;}int ossSocket::bind_listen ()//socket绑定监听{   int rc = EDB_OK ;   int temp = 1 ;   // Allows the socket to be bound to an address that is already in use.   // For database shutdown and restart right away, before socket close   rc = setsockopt ( _fd, SOL_SOCKET,                     SO_REUSEADDR,                     (char*)&temp,                     sizeof (int) );   if ( rc )   {      printf ( "Failed to setsockopt SO_REUSEADDR, rc = %d",              SOCKET_GETLASTERROR ) ;   }   rc = setSocketLi( 1, 30 ) ;   if ( rc )   {      printf ( "Failed to setsockopt SO_LINGER, rc = %d",              SOCKET_GETLASTERROR ) ;   }   rc = ::bind ( _fd, (struct sockaddr *)&_sockAddress, _addressLen ) ;   if ( rc )   {      printf ( "Failed to bind socket, rc = %d", SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }   rc = listen ( _fd, SOMAXCONN ) ;   if ( rc )   {      printf ( "Failed to listen socket, rc = %d", SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }done :   return rc ;error :   close () ;   goto done ;}int ossSocket::send ( const char *pMsg, int len,                        int timeout, int flags ){   int rc = EDB_OK ;   int maxFD = _fd ;   struct timeval maxSelectTime ;   fd_set fds ;   maxSelectTime.tv_sec = timeout / 1000000 ;   maxSelectTime.tv_usec = timeout % 1000000 ;   // if we don't expect to receive anything, no need to continue   if ( 0 == len )      return EDB_OK ;   // wait loop until the socket is ready   while ( true )   {      FD_ZERO ( &fds ) ;      FD_SET ( _fd, &fds ) ;      rc = select ( maxFD + 1, NULL, &fds, NULL,                    timeout>=0?&maxSelectTime:NULL ) ;      // 0 means timeout      if ( 0 == rc )  //超时      {         rc = EDB_TIMEOUT ;         goto done ;      }      // if < 0, means something wrong      if ( 0 > rc ) //失败      {         rc = SOCKET_GETLASTERROR ;         // if we failed due to interrupt, let's continue         if ( EINTR == rc )//如果是一个中断         {            continue ;         }         printf ( "Failed to select from socket, rc = %d",                 rc);         rc = EDB_NETWORK ;         goto error ;      }      // if the socket we interested is not receiving anything, let's continue      if ( FD_ISSET ( _fd, &fds ) )      {         break ;      }   }   while ( len > 0 )//开始发送信息   {      // MSG_NOSIGNAL : Requests not to send SIGPIPE on errors on stream      // oriented sockets when the other end breaks the connection. The EPIPE      // error is still returned.      rc = ::send ( _fd, pMsg, len, MSG_NOSIGNAL|flags ) ;      if ( -1 == rc )      {         printf ( "Failed to send, rc = %d", SOCKET_GETLASTERROR ) ;         rc = EDB_NETWORK ;         goto error ;      }      len -= rc ; //字节数      pMsg += rc ; //起始位置   }   rc = EDB_OK ;done :   return rc ;error :   goto done ;}bool ossSocket::isConnected (){   int rc = EDB_OK ;   // MSG_NOSIGNAL : Requests not to send SIGPIPE on errors on stream   // oriented sockets when the other end breaks the connection. The EPIPE   // error is still returned.   rc = ::send ( _fd, "", 0, MSG_NOSIGNAL ) ;   if ( 0 > rc )   {      return false ;   }   return true ;}//接收消息处理#define MAX_RECV_RETRIES 5int ossSocket::recv ( char *pMsg, int len,                        int timeout, int flags ){   int rc = EDB_OK ;   int retries = 0 ;   int maxFD = _fd ;   struct timeval maxSelectTime ;   fd_set fds ;   // if we don't expect to receive anything, no need to continue   if ( 0 == len )      return EDB_OK ;   maxSelectTime.tv_sec = timeout / 1000000 ;   maxSelectTime.tv_usec = timeout % 1000000 ;   // wait loop until either we timeout or get a message   while ( true )   {      FD_ZERO ( &fds ) ;      FD_SET ( _fd, &fds ) ;      rc = select ( maxFD + 1, &fds, NULL, NULL,                    timeout>=0?&maxSelectTime:NULL ) ;      // 0 means timeout      if ( 0 == rc )  // 如果超时      {         rc = EDB_TIMEOUT ;         goto done ;      }      // if < 0, means something wrong      if ( 0 > rc )  //如果错误      {         rc = SOCKET_GETLASTERROR ;         // if we failed due to interrupt, let's continue         if ( EINTR == rc ) //判断是否是中断引起         {            continue ;         }         printf ( "Failed to select from socket, rc = %d", rc);         rc = EDB_NETWORK ;         goto error ;      }      // if the socket we interested is not receiving anything, let's continue      if ( FD_ISSET ( _fd, &fds ) )      {         break ;      }   }   // Once we start receiving message, there's no chance to timeout, in order to   // prevent partial read   while ( len > 0 ) //开始具体接收处理   {      // MSG_NOSIGNAL : Requests not to send SIGPIPE on errors on stream      // oriented sockets when the other end breaks the connection. The EPIPE      // error is still returned.      rc = ::recv ( _fd, pMsg, len, MSG_NOSIGNAL|flags ) ;      if ( rc > 0 )       {         if ( flags & MSG_PEEK )         {            goto done ;         }         len -= rc ;         pMsg += rc ;      }      else if ( rc == 0 )      {         printf ( "Peer unexpected shutdown" ) ;         rc = EDB_NETWORK_CLOSE ;         goto error ;      }      else      {         // if rc < 0         rc = SOCKET_GETLASTERROR ;         if ( (EAGAIN == rc || EWOULDBLOCK == rc) &&              _timeout > 0 )         {            // if we timeout, it's partial message and we should restart            printf ( "Recv() timeout: rc = %d", rc ) ;            rc = EDB_NETWORK ;            goto error ;         }         if ( ( EINTR == rc ) && ( retries < MAX_RECV_RETRIES ) )         {            // less than max_recv_retries number, let's retry            retries ++ ;            continue ;         }         // something bad when get here         printf ( "Recv() Failed: rc = %d", rc ) ;         rc = EDB_NETWORK ;         goto error ;      }   }   // Everything is fine when get here   rc = EDB_OK ;done :   return rc ;error :   goto done ;}int ossSocket::recvNF ( char *pMsg, int &len,                          int timeout ){   int rc = EDB_OK ;   int retries = 0 ;   int maxFD = _fd ;   struct timeval maxSelectTime ;   fd_set fds ;   // if we don't expect to receive anything, no need to continue   if ( 0 == len )      return EDB_OK ;   maxSelectTime.tv_sec = timeout / 1000000 ;   maxSelectTime.tv_usec = timeout % 1000000 ;   // wait loop until either we timeout or get a message   while ( true )   {      FD_ZERO ( &fds ) ;      FD_SET ( _fd, &fds ) ;      rc = select ( maxFD + 1, &fds, NULL, NULL,                    timeout>=0?&maxSelectTime:NULL ) ;      // 0 means timeout      if ( 0 == rc )      {         rc = EDB_TIMEOUT ;         goto done ;      }      // if < 0, means something wrong      if ( 0 > rc )      {         rc = SOCKET_GETLASTERROR ;         // if we failed due to interrupt, let's continue         if ( EINTR == rc )         {            continue ;         }         printf ( "Failed to select from socket, rc = %d",                 rc);         rc = EDB_NETWORK ;         goto error ;      }      // if the socket we interested is not receiving anything, let's continue      if ( FD_ISSET ( _fd, &fds ) )      {         break ;      }   }   // MSG_NOSIGNAL : Requests not to send SIGPIPE on errors on stream   // oriented sockets when the other end breaks the connection. The EPIPE   // error is still returned.   rc = ::recv ( _fd, pMsg, len, MSG_NOSIGNAL ) ;   if ( rc > 0 )   {      len = rc ;   }   else if ( rc == 0 )   {      printf ( "Peer unexpected shutdown" ) ;      rc = EDB_NETWORK_CLOSE ;      goto error ;   }   else   {      // if rc < 0      rc = SOCKET_GETLASTERROR ;      if ( (EAGAIN == rc || EWOULDBLOCK == rc) &&           _timeout > 0 )      {         // if we timeout, it's partial message and we should restart         printf ( "Recv() timeout: rc = %d", rc ) ;         rc = EDB_NETWORK ;         goto error ;      }      if ( ( EINTR == rc ) && ( retries < MAX_RECV_RETRIES ) )      {         // less than max_recv_retries number, let's retry         retries ++ ;      }      // something bad when get here      printf ( "Recv() Failed: rc = %d", rc ) ;      rc = EDB_NETWORK ;      goto error ;   }   // Everything is fine when get here   rc = EDB_OK ;done :   return rc ;error :   goto done ;}//开始套接字连接int ossSocket::connect (){   int rc = EDB_OK ;   rc = ::connect ( _fd, (struct sockaddr *) &_sockAddress, _addressLen ) ;   if ( rc )   {      printf ( "Failed to connect, rc = %d", SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }   //get local address   rc = getsockname ( _fd, (sockaddr*)&_sockAddress, &_addressLen ) ;//获取本地主机   if ( rc )   {      printf ( "Failed to get local address, rc=%d", rc ) ;      rc = EDB_NETWORK ;      goto error ;   }   //get peer address   rc = getpeername ( _fd, (sockaddr*)&_peerAddress, &_peerAddressLen ) ;//获取对方主机   if ( rc )   {      printf ( "Failed to get peer address, rc=%d", rc ) ;      rc = EDB_NETWORK ;      goto error ;   }done :   return rc ;error :   goto done ;}//关闭套接字连接void ossSocket::close (){   if ( _init )   {      int i = 0 ;      i = ::close ( _fd ) ;      if ( i < 0 )      {         i = -1 ;      }      _init = false ;   }}int ossSocket::accept ( int *sock, struct sockaddr *addr, socklen_t                          *addrlen, int timeout ){   int rc = EDB_OK ;   int maxFD = _fd ;   struct timeval maxSelectTime ;   fd_set fds ;   maxSelectTime.tv_sec = timeout / 1000000 ;   maxSelectTime.tv_usec = timeout % 1000000 ;   while ( true )   {      FD_ZERO ( &fds ) ;      FD_SET ( _fd, &fds ) ;      rc = select ( maxFD + 1, &fds, NULL, NULL,                    timeout>=0?&maxSelectTime:NULL ) ;      // 0 means timeout      if ( 0 == rc )      {         *sock = 0 ;         rc = EDB_TIMEOUT ;         goto done ;      }      // if < 0, means something wrong      if ( 0 > rc )      {         rc = SOCKET_GETLASTERROR ;         // if we failed due to interrupt, let's continue         if ( EINTR == rc )         {            continue ;         }         printf ( "Failed to select from socket, rc = %d", SOCKET_GETLASTERROR);         rc = EDB_NETWORK ;         goto error ;      }      // if the socket we interested is not receiving anything, let's continue      if ( FD_ISSET ( _fd, &fds ) )      {         break ;      }   }   // reset rc back to EDB_OK, since the rc now is the result from select()   rc = EDB_OK ;   *sock = ::accept ( _fd, addr, addrlen ) ;   if ( -1 == *sock )   {      printf ( "Failed to accept socket, rc = %d", SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }done :   return rc ;error :   close () ;   goto done ;}int ossSocket::disableNagle (){   int rc = EDB_OK ;   int temp = 1 ;   rc = setsockopt ( _fd, IPPROTO_TCP, TCP_NODELAY, (char *) &temp,                     sizeof ( int ) ) ;   if ( rc )   {      printf ( "Failed to setsockopt, rc = %d", SOCKET_GETLASTERROR ) ;   }   rc = setsockopt ( _fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &temp,                     sizeof ( int ) ) ;   if ( rc )   {      printf ( "Failed to setsockopt, rc = %d", SOCKET_GETLASTERROR ) ;   }   return rc ;}unsigned int ossSocket::_getPort ( sockaddr_in *addr ){   return ntohs ( addr->sin_port ) ;}int ossSocket::_getAddress ( sockaddr_in *addr, char *pAddress, unsigned int length){   int rc = EDB_OK ;   length = length < NI_MAXHOST ? length : NI_MAXHOST ;   rc = getnameinfo ( (struct sockaddr *)addr, sizeof(sockaddr), pAddress,length,                       NULL, 0, NI_NUMERICHOST ) ;   if ( rc )   {      printf ( "Failed to getnameinfo, rc = %d", SOCKET_GETLASTERROR ) ;      rc = EDB_NETWORK ;      goto error ;   }done :   return rc ;error :   goto done ;}unsigned int ossSocket::getLocalPort (){   return _getPort ( &_sockAddress ) ;}unsigned int ossSocket::getPeerPort (){   return _getPort ( &_peerAddress ) ;}int ossSocket::getLocalAddress ( char * pAddress, unsigned int length ){   return _getAddress ( &_sockAddress, pAddress, length ) ;}int ossSocket::getPeerAddress ( char * pAddress, unsigned int length ){   return _getAddress ( &_peerAddress, pAddress, length ) ;}int ossSocket::setTimeout ( int seconds ){   int rc = EDB_OK ;   struct timeval tv ;   tv.tv_sec = seconds ;   tv.tv_usec = 0 ;   // windows take milliseconds as parameter   // but linux takes timeval as input   rc = setsockopt ( _fd, SOL_SOCKET, SO_RCVTIMEO, ( char* ) &tv,                     sizeof ( tv ) ) ;   if ( rc )   {      printf ( "Failed to setsockopt, rc = %d", SOCKET_GETLASTERROR ) ;   }   rc = setsockopt ( _fd, SOL_SOCKET, SO_SNDTIMEO, ( char* ) &tv,                     sizeof ( tv ) ) ;   if ( rc )   {      printf ( "Failed to setsockopt, rc = %d", SOCKET_GETLASTERROR ) ;   }   return rc ;}int _ossSocket::getHostName ( char *pName, int nameLen ){   return gethostname ( pName, nameLen ) ;}int _ossSocket::getPort ( const char *pServiceName, unsigned short &port ){   int rc = EDB_OK ;   struct servent *servinfo ;   servinfo = getservbyname ( pServiceName, "tcp" ) ;   if ( !servinfo )      port = atoi ( pServiceName ) ;   else      port = (unsigned short)ntohs(servinfo->s_port) ;   return rc ;}//第四步:在Makefile.am中加 oss/ossSocket.cpp,并进行.build.sh进行编译AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=emeralddbemeralddb_SOURCES=\   pmd/pmdMain.cpp \   bson/src/bsonobj.cpp bson/src/util/json.cpp bson/src/oid.cpp \   bson/src/lib/base64.cpp bson/src/lib/md5.cpp bson/src/lib/nonce.cpp \   oss/ossSocket.cppemeralddb_CXXFLAGS=-I../boost -Ibson/src -Iinclude -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0emeralddb_LDADD=-lpthread -lm -lboost_system -lboost_thread -lboost_program_options -lrtemeralddb_LDFLAGS=-fPIC -rdynamic -L../boost/stage/lib -pthread//第五步:实现客户端具体调用代码实现,首先增加头文件,目录文件/emeralddb/src/client/edb.hpp,/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#ifndef _EDB_HPP_#define _EDB_HPP_#include <string>#include <vector>#include "ossSocket.hpp"#include "commandFactory.hpp"const int   CMD_BUFFER_SIZE      =  512;class Edb {public:   Edb(){}   ~Edb(){};public:   void     start(void);protected:   void    prompt(void);private:   void     split(const std::string &text, char delim, std::vector<std::string> &result);   char*    readLine(char *p, int length);   int      readInput(const char *pPrompt, int numIndent);private:   ossSocket      _sock;   CommandFactory _cmdFactory;   char           _cmdBuffer[CMD_BUFFER_SIZE];};#endif//第六步:在客户端目录下增加头文件,目录文件/emeralddb/src/client/commandFactory.hpp/******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#ifndef _COMMAND_FACTORY_HPP_#define _COMMAND_FACTORY_HPP_#include "command.hpp"#define COMMAND_BEGIN void CommandFactory::addCommand() {#define COMMAND_END }#define COMMAND_ADD(cmdName,cmdClass) {                         \   ICommand* pObj = new cmdClass();                             \   std::string str = cmdName;                                   \   _cmdMap.insert(COMMAND_MAP::value_type(str,pObj));           \   }                                                            \class CommandFactory {   typedef std::map<std::string, ICommand*> COMMAND_MAP;   public:      CommandFactory();      ~CommandFactory(){}      void addCommand();      ICommand * getCommandProcesser(const char * pcmd);   private:      COMMAND_MAP _cmdMap;};#endif//第七步:在客户端目录下增加头文件,目录文件/emeralddb/src/client/command.hpp/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#ifndef _COMMAND_HPP_#define _COMMAND_HPP_#include <vector>#include <bson/src/util/json.h>#include "ossSocket.hpp"#define COMMAND_QUIT         "quit"#define COMMAND_INSERT       "insert"#define COMMAND_QUERY        "query"#define COMMAND_DELETE       "delete"#define COMMAND_HELP         "help"#define COMMAND_CONNECT      "connect"#define COMMAND_TEST         "test"#define COMMAND_SNAPSHOT     "snapshot"#define RECV_BUF_SIZE     4096#define SEND_BUF_SIZE     4096#define EDB_QUERY_INVALID_ARGUMENT     -101#define EDB_INSERT_INVALID_ARGUMENT    -102#define EDB_DELETE_INVALID_ARGUMENT    -103#define EDB_INVALID_RECORD              -104#define EDB_RECV_DATA_LENGTH_ERROR     -107#define EDB_SOCK_INIT_FAILED           -113#define EDB_SOCK_CONNECT_FAILED        -114#define EDB_SOCK_NOT_CONNECT           -115#define EDB_SOCK_REMOTE_CLOSED         -116#define EDB_SOCK_SEND_FAILD            -117#define EDB_MSG_BUILD_FAILED           -119class ICommand{   typedef int (*OnMsgBuild)( char ** ppBuffer, int * pBufferSize, \         bson::BSONObj &obj);   public:      virtual int execute( ossSocket & sock, std::vector<std::string> & argVec);      int         getError(int code);   protected:      int      recvReply(ossSocket & sock );      int      sendOrder(ossSocket & sock, OnMsgBuild onMsgBuild );      int      sendOrder(ossSocket & sock, int opCode );   protected:      virtual int handleReply() { return EDB_OK; }   protected:      char _recvBuf[RECV_BUF_SIZE];      char _sendBuf[SEND_BUF_SIZE];      std::string _jsonString;};class ConnectCommand : public ICommand{   public:      int execute ( ossSocket & sock, std::vector<std::string> & argVec );   private:      std::string _address;      int         _port;};class QuitCommand : public ICommand{   public:      int execute(ossSocket & sock, std::vector<std::string> & argVec );   protected:      int handleReply();};class HelpCommand : public ICommand{   public:      int execute(ossSocket & sock, std::vector<std::string> & argVec );};#endif//第八步,定义实现类edb.cpp,是前面edb.h的具体实现/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include <iostream>#include <sstream>#include "edb.hpp"#include "core.hpp"#include "command.hpp"const char    SPACE             =  ' ';const char    TAB               =  '\t';const char    BACK_SLANT        =  '\\';const char    NEW_LINE          =   '\n';int gQuit = 0;void Edb::start(void){   std::cout << "Welcome to EmeraldDB Shell!" << std::endl;   std::cout << "edb help for help, Ctrl+c or quit to exit" << std::endl;   while(0==gQuit)   {      prompt();   }}void Edb:rompt(void){   int ret = EDB_OK;   ret = readInput("edb", 0);   if(ret)   {      return;   }   // Input string   std::string textInput = _cmdBuffer;   // Split the inputing sentence.   std::vector<std::string> textVec;   split(textInput, SPACE, textVec);   int count = 0;   std::string cmd = "";   std::vector<std::string> optionVec;   std::vector<std::string>::iterator iter = textVec.begin();   // handle different command here.   ICommand* pCmd = NULL;   for(;iter != textVec.end(); ++iter)   {      std::string str = *iter;      if(0 == count)      {         cmd = str;         count++;      }      else      {         optionVec.push_back(str);      }   }   pCmd = _cmdFactory.getCommandProcesser(cmd.c_str());   if( NULL != pCmd )   {      pCmd->execute( _sock, optionVec);   }}int Edb::readInput(const char *pPrompt, int numIndent){   memset(_cmdBuffer, 0, CMD_BUFFER_SIZE);   // print tab   for(int i=0; i<numIndent; i++)   {      std::cout << TAB;   }   // print "edb> "   std::cout << pPrompt << ">  ";   // read a line from cmd   readLine(_cmdBuffer,CMD_BUFFER_SIZE-1);   int curBufLen = strlen(_cmdBuffer);   // "\" means continue   while(_cmdBuffer[curBufLen-1] == BACK_SLANT      && (CMD_BUFFER_SIZE-curBufLen) >0)   {      for(int i=0; i<numIndent; i++)      {         std::cout << TAB;      }      std:: cout << "> ";      readLine(&_cmdBuffer[curBufLen-1], CMD_BUFFER_SIZE - curBufLen);   }   curBufLen = strlen(_cmdBuffer);   for( int i = 0; i < curBufLen; i++ )   {      if( _cmdBuffer == TAB )      {         _cmdBuffer = SPACE;      }   }   return EDB_OK;}char *Edb::readLine(char *p, int length){   int len = 0;   int ch;   while((ch=getchar()) != NEW_LINE) {      switch(ch)      {         case BACK_SLANT:            break;         default:            p[len] = ch;            len++;      }      continue;   }   len = strlen(p);   p[len] = 0;   return p;}void Edb::split(const std::string &text, char delim, std::vector<std::string> &result){   size_t strLen = text.length();   size_t first = 0;   size_t pos =0;   for(first=0; first < strLen; first =pos+1)   {      pos = first;      while(text[pos]!= delim && pos<strLen)      {         pos++;      }      std::string str = text.substr(first,pos-first);      result.push_back(str);   }   return;}int main(int argc, char** argv){   Edb edb;   edb.start();   return 0;}//第九步,实现类commandFactory.cpp,是前面commandFactory.h的具体实现/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include "commandFactory.hpp"CommandFactory::CommandFactory(){   addCommand();}ICommand * CommandFactory::getCommandProcesser(const char * pCmd){   ICommand * pProcessor = NULL;   do {      COMMAND_MAP::iterator iter;      iter = _cmdMap.find(pCmd);      if( iter != _cmdMap.end() )      {         pProcessor = iter->second;      }   }while(0);   return pProcessor;}第十步:command.cpp实现类,是command.hpp的具体实现/*******************************************************************************Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include "core.hpp"#include "command.hpp"#include "commandFactory.hpp"COMMAND_BEGINCOMMAND_ADD(COMMAND_CONNECT,ConnectCommand)COMMAND_ADD(COMMAND_QUIT, QuitCommand)COMMAND_ADD(COMMAND_HELP, HelpCommand)COMMAND_ENDextern int gQuit;int ICommand::execute(  ossSocket & sock, std::vector<std::string> & argVec ){   return EDB_OK;}int ICommand::getError(int code){  switch(code)   {      case EDB_OK:         break;      case EDB_IO:         std::cout << "io error is occurred" << std::endl;         break;      case EDB_INVALIDARG:         std::cout << "invalid argument" << std::endl;         break;      case EDB_PERM:         std::cout << "edb_perm" << std::endl;         break;      case EDB_OOM:         std::cout << "edb_oom" << std::endl;         break;      case EDB_SYS:         std::cout << "system error is occurred." << std::endl;         break;      case EDB_QUIESCED:         std::cout << "EDB_QUIESCED" << std::endl;         break;      case EDB_NETWORK_CLOSE:         std::cout << "net work is closed." << std::endl;         break;      case EDB_HEADER_INVALID:         std::cout << "record header is not right." << std::endl;         break;      case EDB_IXM_ID_EXIST:         std::cout << "record key is exist." << std::endl;         break;      case EDB_IXM_ID_NOT_EXIST:         std::cout << "record is not exist" << std::endl;         break;      case EDB_NO_ID:         std::cout << "_id is needed" << std::endl;         break;      case EDB_QUERY_INVALID_ARGUMENT:         std::cout << "invalid query argument" << std::endl;         break;      case EDB_INSERT_INVALID_ARGUMENT:         std::cout <<  "invalid insert argument" << std::endl;         break;      case EDB_DELETE_INVALID_ARGUMENT:         std::cout << "invalid delete argument" << std::endl;         break;      case EDB_INVALID_RECORD:         std::cout << "invalid record string" << std::endl;         break;      case EDB_SOCK_NOT_CONNECT:         std::cout << "sock connection does not exist" << std::endl;         break;      case EDB_SOCK_REMOTE_CLOSED:         std::cout << "remote sock connection is closed" << std::endl;         break;      case EDB_MSG_BUILD_FAILED:         std::cout << "msg build failed" << std::endl;         break;      case EDB_SOCK_SEND_FAILD:         std::cout << "sock send msg faild" << std::endl;         break;      case EDB_SOCK_INIT_FAILED:         std::cout << "sock init failed" << std::endl;         break;      case EDB_SOCK_CONNECT_FAILED:         std::cout << "sock connect remote server failed" << std::endl;         break;      default :         break;   }   return code;}int ICommand::recvReply( ossSocket & sock ){   // define message data length.   int length = 0;   int ret = EDB_OK;   // fill receive buffer with 0.   memset(_recvBuf, 0, RECV_BUF_SIZE);   if( !sock.isConnected() )   {      return getError(EDB_SOCK_NOT_CONNECT);   }   while(1)   {      // receive data from the server.first receive the length of the data.      ret = sock.recv(_recvBuf, sizeof(int));      if( EDB_TIMEOUT == ret )      {         continue;      }      else if( EDB_NETWORK_CLOSE == ret )      {         return getError(EDB_SOCK_REMOTE_CLOSED);      }      else      {         break;      }   }   // get the value of length.   length = *(int*)_recvBuf;   // judge the length is valid or not.   if(length > RECV_BUF_SIZE)   {      return getError(EDB_RECV_DATA_LENGTH_ERROR);   }   // receive data from the server.second receive the last data.   while(1)   {      ret = sock.recv(&_recvBuf[sizeof(int)],length-sizeof(int));      if(ret == EDB_TIMEOUT)      {         continue;      }      else if(EDB_NETWORK_CLOSE == ret)      {         return getError(EDB_SOCK_REMOTE_CLOSED);      }      else      {         break;      }   }   return ret;}int ICommand::sendOrder( ossSocket & sock, OnMsgBuild onMsgBuild  ){   int ret = EDB_OK;   bson::BSONObj bsonData;   try {      bsonData = bson::fromjson(_jsonString);   } catch( std::exception & e) {      return getError(EDB_INVALID_RECORD);   }   memset(_sendBuf,0, SEND_BUF_SIZE);   int size = SEND_BUF_SIZE;   char * pSendBuf = _sendBuf;   ret = onMsgBuild(&pSendBuf, &size, bsonData);   if(ret)   {      return getError(EDB_MSG_BUILD_FAILED);   }   ret = sock.send( pSendBuf, *(int*)pSendBuf );   if(ret)   {      return getError(EDB_SOCK_SEND_FAILD);   }   return ret;}int ICommand::sendOrder( ossSocket & sock, int opCode ){   int ret = EDB_OK;   memset(_sendBuf, 0, SEND_BUF_SIZE);   char * pSendBuf = _sendBuf;   const char *pStr = "hello world" ;   *(int*)pSendBuf=strlen(pStr)+1 + sizeof(int) ;   memcpy ( &pSendBuf[4], pStr, strlen(pStr)+1 ) ;   /*MsgHeader *header = (MsgHeader*)pSendBuf;   header->messageLen = sizeof(MsgHeader);   header->opCode = opCode;*/   ret = sock.send(pSendBuf, *(int*)pSendBuf);   return ret;}/******************************ConnectCommand****************************************/int ConnectCommand::execute( ossSocket & sock, std::vector<std::string> & argVec ){   int rc = EDB_OK;   _address = argVec[0];   _port = atoi(argVec[1].c_str());   sock.close();   sock.setAddress(_address.c_str(), _port);   rc = sock.initSocket();   if ( rc )   {      printf ( "Failed to init socket, rc = %d", rc ) ;      goto error ;   }   rc = sock.connect();   if ( rc )   {      printf ( "Failed to connect, rc = %d", rc ) ;      goto error ;   }   sock.disableNagle();done :   return rc ;error :   goto done ;}/******************************QuitCommand**********************************************/int QuitCommand::handleReply(){   int ret = EDB_OK;   //gQuit = 1;   return ret;}int QuitCommand::execute( ossSocket & sock, std::vector<std::string> & argVec ){   int ret = EDB_OK;   if( !sock.isConnected() )   {      return getError(EDB_SOCK_NOT_CONNECT);   }   ret = sendOrder( sock, 0 );   //sock.close();   ret = handleReply();   return ret;}/******************************HelpCommand**********************************************/int HelpCommand::execute( ossSocket & sock, std::vector<std::string> & argVec ){   int ret = EDB_OK;   printf("List of classes of commands:\n\n";   printf("%s [server] [port]-- connecting emeralddb server\n", COMMAND_CONNECT);   printf("%s -- sending a insert command to emeralddb server\n", COMMAND_INSERT);   printf("%s -- sending a query command to emeralddb server\n", COMMAND_QUERY);   printf("%s -- sending a delete command to emeralddb server\n", COMMAND_DELETE);   printf("%s [number]-- sending a test command to emeralddb server\n", COMMAND_TEST);   printf("%s -- providing current number of record inserting\n", COMMAND_SNAPSHOT);   printf("%s -- quitting command\n\n", COMMAND_QUIT);   printf("Type \"help\" command for help\n";   return ret;}第十一步,修改Makefile.am,增加edb需要操作的源码我的加了后用build.sh编译后报错/usr/bin/ld: ../boost/stage/lib/libboost_thread.a(thread.o): undefined reference to symbol 'pthread_create@@GLIBC_2.1'/usr/bin/ld: note: 'pthread_create@@GLIBC_2.1' is defined in DSO /lib/i386-linux-gnu/libpthread.so.0 so try adding it to the linker command line/lib/i386-linux-gnu/libpthread.so.0: could not read symbols: 无效的操作collect2: 错误: ld 返回 1make[1]: *** [edb] 错误 1make[1]:正在离开目录 `/home/zzk/emeralddb/src'make: *** [all] 错误 2后来把edb_LDADD=-lm -lboost_system -lboost_thread -lrt改为edb_LDADD=-lpthread -lm -lboost_system -lboost_thread -lrt就可以了AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=emeralddb edbemeralddb_SOURCES=\   pmd/pmdMain.cpp \   bson/src/bsonobj.cpp bson/src/util/json.cpp bson/src/oid.cpp \   bson/src/lib/base64.cpp bson/src/lib/md5.cpp bson/src/lib/nonce.cpp \   oss/ossSocket.cppedb_SOURCES=\   client/edb.cpp client/command.cpp client/commandFactory.cpp \   bson/src/bsonobj.cpp bson/src/util/json.cpp bson/src/oid.cpp \   bson/src/lib/base64.cpp bson/src/lib/md5.cpp bson/src/lib/nonce.cpp \   oss/ossSocket.cppemeralddb_CXXFLAGS=-I../boost -Ibson/src -Iinclude -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0emeralddb_LDADD=-lpthread -lm -lboost_system -lboost_thread -lboost_program_options -lrtemeralddb_LDFLAGS=-fPIC -rdynamic -L../boost/stage/lib -pthreadedb_CXXFLAGS=-I../boost -Ibson/src -Iinclude -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0edb_LDADD=-lm -lboost_system -lboost_thread -lrtedb_LDFLAGS=-fPIC -rdynamic -L../boost/stage/lib第十二步:增加socket服务端监听程序,目录文件/emeralddb/src/pmd/pmdTcpListener.cpp/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include "core.hpp"#include "ossSocket.hpp"#define PMD_TCPLISTENER_RETRY 5#define OSS_MAX_SERVICENAME NI_MAXSERVint pmdTcpListenerEntryPoint (){   int rc = EDB_OK ;   int port = 48127 ;   ossSocket sock ( port ) ;   rc = sock.initSocket () ;   if ( rc )   {      printf ( "Failed to initialize socket, rc = %d", rc ) ;      goto error ;   }   rc = sock.bind_listen () ;   if ( rc )   {      printf ( "Failed to bind/listen socket, rc = %d", rc ) ;      goto error ;   }   // master loop for tcp listener   while ( true )   {      int s ;      rc = sock.accept ( &s, NULL, NULL ) ;      // if we don't get anything from period of time, let's loop      if ( EDB_TIMEOUT == rc )      {         rc = EDB_OK ;         continue ;      }      char buffer[1024] ;      int size;      ossSocket sock1 ( &s ) ;      sock1.disableNagle () ;      do      {         rc = sock1.recv ((char*)&size,4 ) ;         if ( rc && rc != EDB_TIMEOUT )         {            printf ( "Failed to receive size, rc = %d", rc ) ;            goto error ;         }      }      while ( EDB_TIMEOUT == rc ) ;      do      {         rc = sock1.recv ( &buffer[0], size-sizeof(int) ) ;         if ( rc && rc != EDB_TIMEOUT )         {            printf ( "Failed to receive buffer, rc = %d", rc ) ;            goto error ;         }      }      while ( EDB_TIMEOUT == rc ) ;      printf ( "%s\n", buffer ) ;      sock1.close () ;   }done:   return rc ;error :   switch ( rc )   {   case EDB_SYS :      printf ( "System error occured" ) ;      break ;   default :      printf ( "Internal error" ) ;   }   goto done ;}//第十三步:修改pmdMain.cpp主调程序/*******************************************************************************   Copyright (C) 2013 SequoiaDB Software Inc.   This program is free software: you can redistribute it and/or modify   it under the terms of the GNU Affero General Public License, version 3,   as published by the Free Software Foundation.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the   GNU Affero General Public License for more details.   You should have received a copy of the GNU Affero General Public License   along with this program. If not, see <http://www.gnu.org/license/>.*******************************************************************************/#include "core.hpp"int pmdTcpListenerEntryPoint () ;int main ( int argc, char **argv ){   pmdTcpListenerEntryPoint () ;   return 0 ;}//第十四步://修改Makefile.am,加pmd/pmdTcpListener.cpp \AUTOMAKE_OPTIONS=foreignbin_PROGRAMS=emeralddb edbemeralddb_SOURCES=\   pmd/pmdMain.cpp pmd/pmdTcpListener.cpp \   bson/src/bsonobj.cpp bson/src/util/json.cpp bson/src/oid.cpp \   bson/src/lib/base64.cpp bson/src/lib/md5.cpp bson/src/lib/nonce.cpp \   oss/ossSocket.cppedb_SOURCES=\   client/edb.cpp client/command.cpp client/commandFactory.cpp \   bson/src/bsonobj.cpp bson/src/util/json.cpp bson/src/oid.cpp \   bson/src/lib/base64.cpp bson/src/lib/md5.cpp bson/src/lib/nonce.cpp \   oss/ossSocket.cppemeralddb_CXXFLAGS=-I../boost -Ibson/src -Iinclude -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0emeralddb_LDADD=-lpthread -lm -lboost_system -lboost_thread -lboost_program_options -lrtemeralddb_LDFLAGS=-fPIC -rdynamic -L../boost/stage/lib -pthreadedb_CXXFLAGS=-I../boost -Ibson/src -Iinclude -D_FILE_OFFSET_BITS=64 -ggdb -Wall -O0edb_LDADD=-lm -lboost_system -lboost_thread -lrtedb_LDFLAGS=-fPIC -rdynamic -L../boost/stage/lib/*第十五步:调试程序gdb emeralddbbreak mainrun step 进入的单步执行l 可查看源码n 不进入的单步执行break 53 在53行增加一个断点c 从断点继续运行查看socket端口是否启动服务 netstat -an | grep 48127
*/