实现最简单的网络服务器[作业]
要求:
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\n"); 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\n"); 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\n"); 54 return false; 55 } 56 57 int backlog = 10; 58 ret = listen(m_socket_fd, backlog); 59 if (ret == -1) { 60 printf("failed listen\n"); 61 return false; 62 } 63 printf("listening on port[%d]\n", 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].\n", 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\n", 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\n"); 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.\n", 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]\n", send_buf); 64 break; 65 } 66 67 ret = recv(m_socket_fd, recv_buf, sizeof(recv_buf), 0); 68 recv_buf[ret] = '\0'; 69 if (ret <= 0) { 70 printf("recv zero msg\n"); 71 continue; 72 } 73 74 printf("recv msg[%s]\n", recv_buf); 75 } // end while 76 77 close(m_socket_fd); 78 } 79 80 }
1 /** 2 tcpclient.cpp 3 */ 4 #include "defs.h" 5 #include "client.h" 6 #include <stdio.h> 7 #include <signal.h> 8 #include <unistd.h> 9 10 void sighandler(int sig) 11 { 12 printf("received signal:%d\n", sig); 13 _exit(1); 14 } 15 16 int main(int argc, char* argv[]) 17 { 18 if (argc != 3) { 19 printf("usage ./client <ip address> <host port>\n"); 20 return 1; 21 } 22 23 struct sigaction act, oact; 24 act.sa_handler = sighandler; 25 sigfillset(&act.sa_mask); 26 act.sa_flags = 0; 27 sigaction(SIGINT, &act, &oact); 28 sigaction(SIGQUIT, &act, &oact); 29 30 webrtc::CClient client; 31 if (!client.connect(argv[1], atoi(argv[2]))) { 32 printf("connect to server[%s:%s] failed.\n", argv[1], argv[2]); 33 return 2; 34 } 35 36 client.run(); 37 38 return 0; 39 } 40 41 # g++ -std=c++11 -g -o tcpclient tcpclient.cpp client.cpp 42 # ./tcpclient 127.0.0.1 8111