• 正文
    • 什么是并發(fā)服務(wù)器
    • 多進程并發(fā)服務(wù)器
    • 多線程并發(fā)服務(wù)器
    • 選擇適合的并發(fā)模型
    • 多進程并發(fā)服務(wù)器代碼實現(xiàn)
    • 多線程并發(fā)服務(wù)器代碼實現(xiàn)
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

并發(fā)服務(wù)器代碼實現(xiàn)(多進程/多線程)

9小時前
139
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

什么是并發(fā)服務(wù)器

當涉及到構(gòu)建高性能的服務(wù)器應(yīng)用程序時,我們通常會考慮使用并發(fā)服務(wù)器來處理多個客戶端請求。在并發(fā)服務(wù)器中,多進程和多線程是兩種常見的并發(fā)模型,它們都有各自的優(yōu)點和適用場景。本文將介紹多進程和多線程并發(fā)服務(wù)器的基礎(chǔ)知識。

多進程并發(fā)服務(wù)器

多進程并發(fā)服務(wù)器通過創(chuàng)建多個子進程來處理客戶端請求。每個子進程是操作系統(tǒng)中獨立運行的單位,擁有自己的內(nèi)存空間和資源。當有新的客戶端連接請求到達時,服務(wù)器創(chuàng)建一個新的子進程來處理該請求。子進程負責與客戶端通信并提供所需的服務(wù)。

多進程并發(fā)服務(wù)器的優(yōu)點是穩(wěn)定性高。由于每個子進程都是相互獨立的,一個子進程的崩潰或錯誤不會影響其他子進程的執(zhí)行。這種獨立性使得多進程并發(fā)服務(wù)器能夠有效地隔離錯誤,提高服務(wù)器的可靠性。

然而,多進程并發(fā)服務(wù)器也有一些缺點。創(chuàng)建和管理多個進程需要消耗更多的系統(tǒng)資源,包括內(nèi)存和CPU時間。進程間的通信也需要特殊的機制,例如管道或共享內(nèi)存,以便在不同進程之間傳遞數(shù)據(jù)。此外,由于每個進程都有自己的內(nèi)存空間,進程間的數(shù)據(jù)共享和同步可能會變得復(fù)雜。

多線程并發(fā)服務(wù)器

多線程并發(fā)服務(wù)器通過創(chuàng)建多個線程來處理客戶端請求。線程是在進程內(nèi)部運行的獨立執(zhí)行流,共享同一個進程的內(nèi)存空間和資源。與多進程不同,多線程服務(wù)器不需要創(chuàng)建新的進程來處理請求,而是在同一個進程中創(chuàng)建多個線程。

多線程并發(fā)服務(wù)器的優(yōu)點是資源消耗較少。與進程相比,線程的創(chuàng)建和切換開銷更小,因為它們共享進程的資源。這使得多線程并發(fā)服務(wù)器更加輕量級,能夠更高效地利用系統(tǒng)資源。

然而,多線程并發(fā)服務(wù)器也存在一些問題。首先,線程共享進程的內(nèi)存空間,因此在多線程環(huán)境中訪問共享數(shù)據(jù)需要特殊的同步機制,以避免競態(tài)條件和數(shù)據(jù)不一致。其次,由于線程共享相同的地址空間,一個線程的錯誤可能會影響整個進程,導(dǎo)致服務(wù)器崩潰或不穩(wěn)定。

選擇適合的并發(fā)模型

在選擇多進程還是多線程并發(fā)服務(wù)器時,需要根據(jù)具體的應(yīng)用需求和性能要求進行權(quán)衡。以下是一些建議:

- 如果穩(wěn)定性和容錯性是首要考慮因素,多進程并發(fā)服務(wù)器可能是更好的選擇。每個子進程的獨立性可以有效地隔離錯誤,提高服務(wù)器的可靠性。

- 如果服務(wù)器需要處理大量的并發(fā)連接并需要更高的性能和資源利用率,多線程并發(fā)服務(wù)器可能更適合。線程的創(chuàng)建和切換開銷相對較小,可以更高效地處理并發(fā)請求。

- 如果同時需要穩(wěn)定性和性能,可以考慮使用混合模型,即在每個進程中創(chuàng)建多個線程,以實現(xiàn)更好的負載平衡和資源利用率。

無論選擇多進程還是多線程并發(fā)服務(wù)器,都需要注意正確處理并發(fā)訪問共享數(shù)據(jù)的問題,使用適當?shù)耐綑C制(如鎖、信號量)來保證數(shù)據(jù)的一致性和正確性。

總結(jié)起來,多進程和多線程并發(fā)服務(wù)器是實現(xiàn)高性能服務(wù)器的常見方式。它們各有優(yōu)劣,選擇合適的并發(fā)模型需要考慮應(yīng)用需求和性能要求,并注意處理并發(fā)訪問共享數(shù)據(jù)的問題。

多進程并發(fā)服務(wù)器代碼實現(xiàn)

使用多進程并發(fā)服務(wù)器時要考慮以下幾點:

- 父進程最大文件描述個數(shù)(父進程中需要close關(guān)閉accept返回的新文件描述符);

- 系統(tǒng)內(nèi)創(chuàng)建進程個數(shù)(與內(nèi)存大小相關(guān));

-進程創(chuàng)建過多是否降低整體服務(wù)性能(進程調(diào)度);

server

/* server.c */#include<stdio.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<signal.h>#include<sys/wait.h>#include<sys/types.h>#include"wrap.h"
#define?MAXLINE 80#define?SERV_PORT 800
voiddo_sigchild(int?num){while?(waitpid(0,?NULL, WNOHANG) >?0)? ? ;}intmain(void){structsockaddr_inservaddr, cliaddr;socklen_t?cliaddr_len;int?listenfd, connfd;char?buf[MAXLINE];char?str[INET_ADDRSTRLEN];int?i, n;pid_t?pid;
structsigactionnewact;? newact.sa_handler = do_sigchild;??sigemptyset(&newact.sa_mask);? newact.sa_flags =?0;??sigaction(SIGCHLD, &newact,?NULL);
? listenfd =?Socket(AF_INET, SOCK_STREAM,?0);
??bzero(&servaddr,?sizeof(servaddr));? servaddr.sin_family = AF_INET;? servaddr.sin_addr.s_addr =?htonl(INADDR_ANY);? servaddr.sin_port =?htons(SERV_PORT);
??Bind(listenfd, (struct?sockaddr *)&servaddr,?sizeof(servaddr));
??Listen(listenfd,?20);
printf("Accepting connections ...n");while?(1) {? ? cliaddr_len =?sizeof(cliaddr);? ? connfd =?Accept(listenfd, (struct?sockaddr *)&cliaddr, &cliaddr_len);
? ? pid = fork();if?(pid ==?0) {? ? ??Close(listenfd);while?(1) {? ? ? ? n =?Read(connfd, buf, MAXLINE);if?(n ==?0) {printf("the other side has been closed.n");break;? ? ? ? }printf("received from %s at PORT %dn",? ? ? ? ? ??inet_ntop(AF_INET, &cliaddr.sin_addr, str,?sizeof(str)),? ? ? ? ? ??ntohs(cliaddr.sin_port));for?(i =?0; i < n; i++)? ? ? ? ? buf[i] =?toupper(buf[i]);? ? ? ??Write(connfd, buf, n);? ? ? }? ? ??Close(connfd);return0;? ? }?elseif?(pid >?0) {? ? ??Close(connfd);? ? }?else? ? ??perr_exit("fork");? }??Close(listenfd);return0;}

client:

/* client.c */#include<stdio.h>#include<string.h>#include<unistd.h>#include<netinet/in.h>#include"wrap.h"
#define?MAXLINE 80#define?SERV_PORT 6666
intmain(int?argc,?char?*argv[]){structsockaddr_inservaddr;char?buf[MAXLINE];int?sockfd, n;
? sockfd =?Socket(AF_INET, SOCK_STREAM,?0);
??bzero(&servaddr,?sizeof(servaddr));? servaddr.sin_family = AF_INET;??inet_pton(AF_INET,?"127.0.0.1", &servaddr.sin_addr);? servaddr.sin_port =?htons(SERV_PORT);
??Connect(sockfd, (struct?sockaddr *)&servaddr,?sizeof(servaddr));
while?(fgets(buf, MAXLINE, stdin) !=?NULL) {? ??Write(sockfd, buf,?strlen(buf));? ? n =?Read(sockfd, buf, MAXLINE);if?(n ==?0) {printf("the other side has been closed.n");break;? ? }?else? ? ??Write(STDOUT_FILENO, buf, n);? }??Close(sockfd);return0;}

多線程并發(fā)服務(wù)器代碼實現(xiàn)

在使用線程模型開發(fā)服務(wù)器時需考慮以下問題:

- 調(diào)整進程內(nèi)最大文件描述符上限;

- 線程如有共享數(shù)據(jù),考慮線程同步;

- 服務(wù)于客戶端線程退出時,退出處理(退出值,分離態(tài));

- 系統(tǒng)負載,隨著鏈接客戶端增加,導(dǎo)致其它線程不能及時得到CPU;

server:

/* server.c */#include<stdio.h>#include<string.h>#include<netinet/in.h>#include<arpa/inet.h>#include<pthread.h>
#include"wrap.h"#define?MAXLINE 80#define?SERV_PORT 6666
structs_info {structsockaddr_incliaddr;int?connfd;};void?*do_work(void?*arg){int?n,i;structs_info *ts = (structs_info*)arg;char?buf[MAXLINE];char?str[INET_ADDRSTRLEN];/* 可以在創(chuàng)建線程前設(shè)置線程創(chuàng)建屬性,設(shè)為分離態(tài),哪種效率高內(nèi)?*/??pthread_detach(pthread_self());while?(1) {? ? n =?Read(ts->connfd, buf, MAXLINE);if?(n ==?0) {printf("the other side has been closed.n");break;? ? }printf("received from %s at PORT %dn",? ? ? ??inet_ntop(AF_INET, &(*ts).cliaddr.sin_addr, str,?sizeof(str)),? ? ? ??ntohs((*ts).cliaddr.sin_port));for?(i =?0; i < n; i++)? ? ? buf[i] =?toupper(buf[i]);? ??Write(ts->connfd, buf, n);? }??Close(ts->connfd);}
intmain(void){structsockaddr_inservaddr, cliaddr;socklen_t?cliaddr_len;int?listenfd, connfd;int?i =?0;pthread_t?tid;structs_infots[256];
? listenfd =?Socket(AF_INET, SOCK_STREAM,?0);
??bzero(&servaddr,?sizeof(servaddr));? servaddr.sin_family = AF_INET;? servaddr.sin_addr.s_addr =?htonl(INADDR_ANY);? servaddr.sin_port =?htons(SERV_PORT);
??Bind(listenfd, (struct?sockaddr *)&servaddr,?sizeof(servaddr));??Listen(listenfd,?20);
printf("Accepting connections ...n");while?(1) {? ? cliaddr_len =?sizeof(cliaddr);? ? connfd =?Accept(listenfd, (struct?sockaddr *)&cliaddr, &cliaddr_len);? ? ts[i].cliaddr = cliaddr;? ? ts[i].connfd = connfd;/* 達到線程最大數(shù)時,pthread_create出錯處理, 增加服務(wù)器穩(wěn)定性 */? ??pthread_create(&tid,?NULL, do_work, (void*)&ts[i]);? ? i++;? }return0;}

client:

/* client.c */#include<stdio.h>#include<string.h>#include<unistd.h>#include<netinet/in.h>#include"wrap.h"#define?MAXLINE 80#define?SERV_PORT 6666intmain(int?argc,?char?*argv[]){structsockaddr_inservaddr;char?buf[MAXLINE];int?sockfd, n;
? sockfd =?Socket(AF_INET, SOCK_STREAM,?0);
??bzero(&servaddr,?sizeof(servaddr));? servaddr.sin_family = AF_INET;??inet_pton(AF_INET,?"127.0.0.1", &servaddr.sin_addr);? servaddr.sin_port =?htons(SERV_PORT);
??Connect(sockfd, (struct?sockaddr *)&servaddr,?sizeof(servaddr));
while?(fgets(buf, MAXLINE, stdin) !=?NULL) {? ??Write(sockfd, buf,?strlen(buf));? ? n =?Read(sockfd, buf, MAXLINE);if?(n ==?0)printf("the other side has been closed.n");else? ? ??Write(STDOUT_FILENO, buf, n);? }??Close(sockfd);return0;}

 

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

Linux、C、C++、Python、Matlab,機器人運動控制、多機器人協(xié)作,智能優(yōu)化算法,貝葉斯濾波與卡爾曼濾波估計、多傳感器信息融合,機器學(xué)習(xí),人工智能。