📄 tcp_server.c
字号:
#include "tcp_server.h"#include "config.h"#include <fstream.h>#include <iostream.h>#ifdef DEFINE_SOCKLEN_T typedef unsigned int socklen_t ;#endifstatic int glob_sock_fd = -1;static void reaper(int sig_num); // this one has to be outside of classstatic void do_cleanup(int sig_num);static void do_cleanup(int sig_num);static void do_cleanup(int ) { if(glob_sock_fd >= 0) close(glob_sock_fd); exit(0); }static void reaper(int) { int status; while (waitpid(-1, &status, WNOHANG) > 0) signal(SIGCHLD, reaper); }void TcpServer::start_server(int port, int listen_queue_size, char* log_file) { if(!log_file) log = stderr; else if(!strcmp("-", log_file)) log = stderr; else { log = fopen(log_file, "a"); if(!log) { fprintf(stderr, "Tcp Server: could not open log file %s : %s\n", log_file, strerror(errno)); exit(1); } } setbuf(log, NULL); struct protoent *tcp_prot = getprotobyname("tcp"); if(!tcp_prot) fatal_error("TcpServer: tcp does not seem to be supported"); socket_fd = socket(AF_INET,SOCK_STREAM, tcp_prot->p_proto); if(socket_fd == -1) fatal_error("TcpServer: error creating the socket: %s", strerror(errno)); glob_sock_fd = socket_fd; // this is for the signal handlers int one = 1; if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) fatal_error("TcpServer: failed on setsockopt(): %s", strerror(errno)); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(port); serv_addr.sin_family = AF_INET; if(bind(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) { fatal_error("TcpServer: Could not bind: %s", strerror(errno)); } if(listen(socket_fd, listen_queue_size) == -1) fatal_error("TcpServer: could not listen: %s", strerror(errno)); signal(SIGTERM, do_cleanup); }void TcpServer::run_server() { pid_t fork_pid = fork(); if(fork_pid == -1) fatal_error("TcpServer: could not fork into background: %s", strerror(errno)); signal(SIGCHLD, reaper); if(fork_pid > 0) { close(socket_fd); return; } close(0); close(1); close(2); socklen_t serv_addr_size = sizeof(serv_addr); while(1) { int client_socket_fd = accept(socket_fd, (struct sockaddr*)&serv_addr, &serv_addr_size); if(client_socket_fd == -1) { if(errno != EINTR) warn( "TcpServer: error on accept : %s\n", strerror(errno)); } else { int client_fork_pid = fork(); if(client_fork_pid == -1) warn("TcpServer: could not fork off a client handler : %s\n", strerror(errno)); else if(client_fork_pid == 0) { close(socket_fd); if(access_control) if(!access_allowed(client_socket_fd)) { close(client_socket_fd); return; } handle_client(client_socket_fd); close(client_socket_fd); return; } else close(client_socket_fd); } } } TcpServer::TcpServer(int port,int listen_queue_size, char* log_file): debug_level(0), access_control(0) { start_server(port, listen_queue_size, log_file); }TcpServer::~TcpServer() { }int TcpServer::access_allowed(int client_socket_fd) { struct sockaddr_in peername; socklen_t peername_len = sizeof(sockaddr_in); if(getpeername(client_socket_fd, (struct sockaddr*)&peername, &peername_len) == -1) { warn("Cannot get peer - access denied"); return 0; } else { if(ip_rules.ok(peername.sin_addr)) return 1; char* src_addr = inet_ntoa(peername.sin_addr); log_access_denied(src_addr); } return 0; }char* TcpServer::get_peer_addr(int client_socket_fd) { struct sockaddr_in peername; socklen_t peername_len = sizeof(sockaddr_in); if(getpeername(client_socket_fd, (struct sockaddr*)&peername, &peername_len) == -1) warn("Cannot get peer"); else { char* src_addr = inet_ntoa(peername.sin_addr); return src_addr; } return "unknown"; }void TcpServer::cleanup() { if(socket_fd >= 0) close(socket_fd); }#ifdef DEBUGclass TestServer: public TcpServer { protected: void handle_client(int client_socket_fd); public: TestServer(int port, int queue_size, char* log_file) : TcpServer(port, queue_size, log_file) { } };void TestServer::handle_client(int client_socket_fd) { char buf[512]; info("connect from %s ", get_peer_addr(client_socket_fd)); FILE *in = fdopen(client_socket_fd, "r"); FILE *out = fdopen(client_socket_fd, "w"); setbuf(in, NULL); setbuf(out, NULL); if(!in) { warn("fdopen failed on 'in': %s\n", strerror(errno)); return; } if(!out) { warn("fdopen failed on 'out': %s\n", strerror(errno)); return; } fprintf(out, "Please enter your name:"); fgets( buf, sizeof(buf), in); fprintf(out, "Good-bye, %s\n", buf); }int main(int c, char** argv) { int port = 1234; char* log_file = "-"; char* ip_rules_file = NULL; if(c > 1) port = atoi(argv[1]); if(c > 2) log_file = argv[2]; if(c > 3) ip_rules_file = argv[3]; TestServer s(port, 50, log_file); if(ip_rules_file) { ifstream rules(ip_rules_file); if(!rules) { cerr << "Could not open rules file" << endl; exit(1); } while(1) { char netnum[128], netmask[128]; rules >> netnum >> netmask; cout << "reading: " << netnum << " " << netmask << endl; if(!rules) break; s.add_ip_rule(netnum, netmask); } s.enable_access_control(); } s.run_server(); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -