https://blog.csdn.net/lianghe_work/article/details/46503895
一、tcp并發服務器概述
一個好的服務器,一般都是并發服務器(同一時刻可以響應多個客戶端的請求)。并發服務器設計技術一般有:多進程服務器、多線程服務器、I/O復用服務器等。
二、多進程并發服務器
在 Linux 環境下多進程的應用很多,其中最主要的就是網絡/客戶服務器。多進程服務器是當客戶有請求時,服務器用一個子進程來處理客戶請求。父進程繼續等待其它客戶的請求。這種方法的優點是當客戶有請求時,服務器能及時處理客戶,特別是在客戶服務器交互系統中。對于一個 TCP 服務器,客戶與服務器的連接可能并不馬上關閉,可能會等到客戶提交某些數據后再關閉,這段時間服務器端的進程會阻塞,所以這時操作系統可能調度其它客戶服務進程,這比起循環服務器大大提高了服務性能。
發達
tcp多進程并發服務器
TCP 并發服務器的思想是每一個客戶機的請求并不由服務器直接處理,而是由服務器創建一個子進程來處理。
tcp多進程并發服務器參考代碼:
/************************************************************************ 函數名稱: void main(int argc, char *argv[]) 函數功能: 主函數,用進程建立一個TCP Echo Server 函數參數: 無 函數返回: 無 ************************************************************************/ int main(int argc, char *argv[]) { unsigned short port = 8080; // 本地端口 //1.創建tcp套接字 int sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) { perror("socket"); exit(-1); } //配置本地網絡信息 struct sockaddr_in my_addr; bzero(&my_addr, sizeof(my_addr)); // 清空 my_addr.sin_family = AF_INET; // IPv4 my_addr.sin_port = htons(port); // 端口 my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip //2.綁定 int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr)); if( err_log != 0) { perror("binding"); close(sockfd); exit(-1); } //3.監聽,套接字變被動 err_log = listen(sockfd, 10); if(err_log != 0) { perror("listen"); close(sockfd); exit(-1); } while(1) //主進程 循環等待客戶端的連接 { char cli_ip[INET_ADDRSTRLEN] = {0}; struct sockaddr_in client_addr; socklen_t cliaddr_len = sizeof(client_addr); // 取出客戶端已完成的連接 int connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len); if(connfd < 0) { perror("accept"); close(sockfd); exit(-1); } pid_t pid = fork(); if(pid < 0){ perror("fork"); _exit(-1); }else if(0 == pid){ //子進程 接收客戶端的信息,并發還給客戶端 /*關閉不需要的套接字可節省系統資源, 同時可避免父子進程共享這些套接字 可能帶來的不可預計的后果 */ close(sockfd); // 關閉監聽套接字,這個套接字是從父進程繼承過來 char recv_buf[1024] = {0}; int recv_len = 0; // 打印客戶端的 ip 和端口 memset(cli_ip, 0, sizeof(cli_ip)); // 清空 inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN); printf("----------------------------------------------\n"); printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port)); // 接收數據 while( (recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0 ) { printf("recv_buf: %s\n", recv_buf); // 打印數據 send(connfd, recv_buf, recv_len, 0); // 給客戶端回數據 } printf("client_port %d closed!\n", ntohs(client_addr.sin_port)); close(connfd); //關閉已連接套接字 exit(0); } else if(pid > 0){ // 父進程 close(connfd); //關閉已連接套接字 } } close(sockfd); return 0; }運行結果: