【Linux网络编程】并发服务器之多进程模型
生活随笔
收集整理的這篇文章主要介紹了
【Linux网络编程】并发服务器之多进程模型
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
00. 目錄
文章目錄
- 00. 目錄
- 01. 概述
- 02. 多進程并發服務器
- 03. 多進程并發服務器實現思路
- 04. 多進程并發服務器實現
- 05. 附錄
01. 概述
服務器設計技術有很多,按使用的協議來分有 TCP 服務器和 UDP 服務器,按處理方式來分有循環服務器和并發服務器。
循環服務器與并發服務器模型
在網絡程序里面,一般來說都是許多客戶對應一個服務器(多對一),為了處理客戶的請求,對服務端的程序就提出了特殊的要求。
目前最常用的服務器模型
- 循環服務器:服務器在同一時刻只能響應一個客戶端的請求。
- 并發服務器:服務器在同一時刻可以響應多個客戶端的請求。
02. 多進程并發服務器
一個好的服務器,一般都是并發服務器(同一時刻可以響應多個客戶端的請求)。并發服務器設計技術一般有:多進程服務器、多線程服務器、I/O復用服務器等。
在 Linux 環境下多進程的應用很多,其中最主要的就是網絡/客戶服務器。多進程服務器是當客戶有請求時,服務器用一個子進程來處理客戶請求。父進程繼續等待其它客戶的請求。這種方法的優點是當客戶有請求時,服務器能及時處理客戶,特別是在客戶服務器交互系統中。對于一個 TCP 服務器,客戶與服務器的連接可能并不馬上關閉,可能會等到客戶提交某些數據后再關閉,這段時間服務器端的進程會阻塞,所以這時操作系統可能調度其它客戶服務進程,這比起循環服務器大大提高了服務性能。
03. 多進程并發服務器實現思路
TCP 并發服務器的思想是每一個客戶機的請求并不由服務器直接處理,而是由服務器創建一個子進程來處理。
#include <頭文件>int main(void) {//創建套接字//綁定套接字//設置監聽while(1){int connfd = accept();//子進程if (0 == fork()){//關閉監聽套接字close(sockfd);//數據處理//關閉連接套接字close(connfd);exit(0);}//關閉已經連接的套接字close(connfd);}close(sockfd);return 0; }04. 多進程并發服務器實現
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main(int argc, char *argv[]) {unsigned short port = 8080; // 本地端口 // 創建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; // IPv4my_addr.sin_port = htons(port); // 端口my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip// 綁定int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));if( err_log != 0){perror("binding");close(sockfd); exit(-1);}// 監聽,套接字變被動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 closed!\n");close(connfd); //關閉已連接套接字exit(0);}else if(pid > 0){ // 父進程close(connfd); //關閉已連接套接字}}close(sockfd);return 0; }05. 附錄
【Linux】一步一步學Linux網絡編程教程匯總
總結
以上是生活随笔為你收集整理的【Linux网络编程】并发服务器之多进程模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux网络编程】循环服务器之TCP
- 下一篇: 【Linux网络编程】并发服务器之多线程