实现最简单的网络服务器[作业]

要求:

1.客户端与服务端可以通过TCP通信;

2.处理常见的信号(SIGINT, SIGQUIT, SIGHUP, SIGPIPE, SIGCHLD);

3.服务器在后台运行;

4.使用C++实现;

 1 /**
 2   defs.h
 3 */
 4 #ifndef _DEFS_H_
 5 #define _DEFS_H_
 6 
 7 #include <signal.h>
 8 #include <assert.h>
 9 #include <iostream>
10 
11 #define PORT 8111
12 #define MSG_LEN 1024
13 
14 typedef enum NETWORK_TYPE
15 {
16     NETWORK_TCP = 0,
17     NETWORK_UDP = 1
18 } NETWORK_TYPE;
19 
20 #endif    // _DEFS_H_
 1 /**
 2   server.h
 3 */
 4 #ifndef _CSERVER_H_
 5 #define _CSERVER_H_
 6 
 7 #include "defs.h"
 8 
 9 namespace webrtc {
10 
11 class CServer
12 {
13 public:
14     CServer(int port, NETWORK_TYPE type);
15     ~CServer();
16 
17 public:
18     void registerSignals(int sig, void(*handle)(int));
19     void run();
20 
21 private:
22     class CInternal;
23     CInternal*    m_internal;
24 };
25 
26 }
27 
28 #endif    // _CSERVER_H_
 1 /**
 2   internal.h
 3 */
 4 #ifndef _INTERNAL_H_
 5 #define _INTERNAL_H_
 6 
 7 #include "server.h"
 8 #include <stdio.h>
 9 #include <unistd.h>
10 #include <string.h>
11 #include <strings.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 
16 namespace webrtc
17 {
18 
19 class CServer::CInternal
20 {
21 public:
22     CInternal(int port, NETWORK_TYPE type);
23     ~CInternal();
24     
25 public:
26     void registerSignals(int sig, void(*handle)(int));
27     bool start();
28     void run();
29 
30 private:
31     int m_port;
32     NETWORK_TYPE m_type;
33     int m_socket_fd;
34     char *m_buff;
35     struct sockaddr_in m_local_addr;
36 };
37 
38 }    // end webrtc
39 
40 #endif    // _INTERNAL_H_
  1 /**
  2   server.cpp
  3 */
  4 #include "internal.h"
  5 #include <signal.h>
  6 
  7 namespace webrtc 
  8 {
  9 
 10 CServer::CInternal::CInternal(int port, NETWORK_TYPE type)
 11     : m_port(port)
 12     , m_type(type)
 13     , m_socket_fd(-1)
 14     , m_buff(NULL)
 15 {
 16     m_buff = new char[MSG_LEN];
 17 }
 18 
 19 CServer::CInternal::~CInternal()
 20 {
 21     if (m_buff != NULL) {
 22         delete[] m_buff;
 23         m_buff = NULL;
 24     }
 25 
 26     if (m_socket_fd > 0) {
 27         close(m_socket_fd);
 28         m_socket_fd = -1;
 29     }
 30 }
 31 
 32 bool CServer::CInternal::start()
 33 {
 34     m_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
 35     if (socket_fd == -1) {
 36         printf("can't create socket fd
");
 37         return false;
 38     }
 39 
 40     int on = 1;
 41     int ret = setsockopt(m_socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
 42     if (ret == -1) {
 43         printf("faild to set socket option
");
 44     }
 45 
 46     bzero(&m_local_addr, sizeof(m_local_addr));
 47     m_local_addr.sin_family = AF_INET;
 48     m_local_addr.sin_port = htons(m_port);
 49     m_local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
 50     socklen_t addr_len = sizeof(struct sockaddr_in);
 51     ret = bind(m_socket_fd, (struct sockaddr *)&m_local_addr, addr_len);
 52     if (ret == -1) {
 53         printf("failed to bind addr
");
 54         return false;
 55     }
 56 
 57     int backlog = 10;
 58     ret = listen(m_socket_fd, backlog);
 59     if (ret == -1) {
 60         printf("failed listen
");
 61         return false;
 62     }
 63     printf("listening on port[%d]
", m_port);
 64 
 65     return true;
 66 }
 67 
 68 void CServer::CInternal::registerSignals(int sig, void(*handle)(int))
 69 {
 70     std::cout << "register sig:" << sig << std::endl;
 71     signal(sig, handle);
 72 }
 73 
 74 void CServer::CInternal::run()
 75 {
 76     if (!start()) {
 77         printf("start server failed, port[%d].
", m_po);
 78         return;
 79     }
 80 
 81     std::cout << "run..." << std::endl;
 82     int ret = -1;
 83     int accept_fd;
 84     struct sockaddr_in remote_addr;
 85     bzero(&remote_addr, sizeof(remote_addr));
 86     socklen_t addr_len = sizeof(struct sockaddr_in);
 87     while (true) {
 88         accept_fd = accept(m_socket_fd, (struct sockaddr *)&remoteaddr, &addr_len);
 89         if (accept_fd <= 0) 
 90             continue;
 91 
 92         while (true) {
 93             memset(m_buff, 0, sizeof(m_buff));
 94             ret = recv(accept_fd, (void *)in_buff, MESSAGE_LEN, 0);
 95             if (ret == 0) 
 96                 break;
 97 
 98             printf("recv:%s
", in_buff);
 99             send(accept_fd, (void *)in_buff, MESSAGE_LEN, 0);
100         } // end while
101 
102         close(accept_fd);
103     } //end while
104 }
105 
106 CServer::CServer(int port, NETWORK_TYPE type)
107     : m_internal(NULL)
108 {
109     m_internal = new CInternal(port, type);
110     assert(m_internal != NULL);
111 }
112 
113 CServer::~CServer()
114 {
115     delete m_internal;
116     m_internal = NULL;
117 }
118 
119 void CServer::registerSignals(int sig, void(*handle)(int))
120 {
121     if (m_internal != NULL)
122     {
123         m_internal->registerSignals(sig, handle);
124     }
125 }
126 
127 void CServer::run()
128 {
129     if (m_internal != NULL)
130     {
131         m_internal->run();
132     }
133 }
134 
135 }    // end webrtc
 1 /**
 2   tcpserver.cpp
 3 */
 4 #include <iostream>
 5 #include "server.h"
 6 
 7 using namespace webrtc;
 8 
 9 void sighandle(int sig) 
10 {
11     std::cout << "sig:" << sig << std::endl;
12     if (sig == SIGINT)
13     {
14         _exit(0);
15     }
16 }
17 
18 int main(int argc, char* argv[])
19 {
20     CServer* server = new CServer(PORT, NETWORK_TCP);
21     server->registerSignals(SIGINT, sighandle);
22     server->registerSignals(SIGQUIT, sighandle);
23     server->registerSignals(SIGCHLD, sighandle);
24     server->registerSignals(SIGPIPE, sighandle);
25     server->registerSignals(SIGHUP, sighandle);
26 
27     server->run();
28 
29     return 0;
30 }
31 
32 # g++ -std=c++11 -g -o tcpserver tcpserver.cpp server.cpp
33 # ./tcpserver
 1 /**
 2   client.h
 3 */
 4 #ifndef _CCLIENT_H_
 5 #define _CCLIENT_H_
 6 
 7 #include "defs.h"
 8 #include <iostream>
 9 
10 namespace webrtc {
11 
12 class CClient
13 {
14 public:
15     CClient();
16     ~CClient();
17 
18 public:
19     bool connect(const std::string& address, int port);
20     void run();
21 
22 private:
23     int m_socket_fd;
24 };
25 
26 }
27 
28 #endif
 1 /**
 2   client.cpp
 3 */
 4 #include "client.h"
 5 #include <stdio.h>
 6 #include <string.h>
 7 #include <unistd.h>
 8 #include <sys/types.h>
 9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <arpa/inet.h>
12 
13 namespace webrtc
14 {
15 
16 CClient::CClient()
17     : m_socket_fd(-1)
18 {}
19 
20 CClient::~CClient()
21 {}
22 
23 bool CClient::connect(const std::string& address, int port)
24 {
25     int ret = -1;
26     struct sockaddr_in server_addr;
27     socklen_t addr_len;
28 
29     m_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
30     if (m_socket_fd < 0) {
31         printf("failed create socket
");
32         return false;
33     }
34 
35     bzero(&server_addr, sizeof(server_addr));
36     server_addr.sin_family = AF_INET;
37     server_addr.sin_port = htons(port);
38     server_addr.sin_addr.s_addr = inet_addr(address.c_str());
39     addr_len  = sizeof(struct sockaddr_in);
40     ret = ::connect(m_socket_fd, (struct sockaddr *)&server_addr, addr_len);
41     if (ret < 0) {;
42         return false;
43     }
44     printf("connect to server[%s:%d] success.
", address.c_str(), port);
45 
46     return true;
47 }
48 
49 void CClient::run()
50 {
51     int ret = -1;
52     char send_buf[MSG_LEN] = { 0 };
53     char recv_buf[MSG_LEN] = { 0 };
54     while (1) {
55         memset(send_buf, 0, sizeof(send_buf));
56         memset(recv_buf, 0, sizeof(recv_buf));
57         gets(send_buf);
58         if (strncmp(send_buf, "quit", 4) == 0)
59             break;
60 
61         ret = send(m_socket_fd, send_buf, strlen(send_buf), 0);
62         if (ret <= 0) {
63             printf("failed send msg[%s]
", send_buf);
64             break;
65         }
66 
67         ret = recv(m_socket_fd, recv_buf, sizeof(recv_buf), 0);
68         recv_buf[ret] = '