日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

socket网络编程——多进程、多线程处理并发

發布時間:2024/4/17 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 socket网络编程——多进程、多线程处理并发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.服務器處理并發的必要性

如下圖所示, 當一個客戶端與服務器建立連接以后,服務器端 accept()返回,進而準備循環接收客戶端發過來的數據。如果客戶端暫時沒發數據,服務端會在 recv()處阻塞。此時,其他客戶端向服務器發起連接后,由于服務器阻塞了,無法執行 accept()接受連接,也就是其他客戶端發送的數據,服務器無法讀取。服務器也就無法并發同時處理多個客戶端。

這個問題可以通過引入多線程和多進程來解決。服務端接受一個客戶端的連接后,創建一個線程或者進程,然后在新創建的線程或進程中循環處理數據。主線程(父進程)只負責監聽客戶端的連接,并使用 accept()接受連接,不進行數據的處理。如下圖所示:

2.多線程處理并發

服務器端示例代碼 thread_server.c 如下:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<sys/socket.h> #include<arpa/inet.h> #include<pthread.h>void* pthread_fun(void* arg) {int c = *(int*)arg;while(1){char buff[128] = {0};int n = recv(c,buff,127,0);if(n <= 0){break;}printf("recv(%d)=%s\n",c,buff);send(c,"OK",2,0);} }int main() {int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd != -1);struct sockaddr_in saddr,caddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1);listen(sockfd,5);while(1){int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);if(c < 0){continue;}printf("accept = %d\n",c);pthread_t id;pthread_create(&id,NULL,pthread_fun,(void*)&c);}close(sockfd);exit(0); }

運行結果
打開服務端,獲取客戶端發送的消息:

分別打開三個客戶端,并且輸入值:


3.多進程處理并發

服務器端示例代碼process_server.c 如下:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<sys/socket.h> #include<arpa/inet.h> #include<signal.h>void recv_fun(int c, struct sockaddr_in caddr) {while(1){char buff[128] = {0};int n = recv(c,buff,127,0);if(n <= 0){break;}printf("%s:%d %s\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port),buff);send(c,"OK",2,0);} }void sigfun() {wait(NULL); }int main() {signal(SIGCHLD,sigfun);//子進程結束會給父進程發送SIGCHLD信號,sigfun處理int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd != -1);struct sockaddr_in saddr,caddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//將一個點分十進制的IP轉換成一個長整型數int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1);listen(sockfd,5);while(1){int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);assert(c != -1);printf("%s:%d Link Sucess\n",inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));//inet_ntoa是將網絡地址轉化為“.”隔的字符串格式pid_t pid = fork();assert(pid != -1);if(pid == 0){recv_fun(c,caddr);exit(0);//必須結束子進程,否則會有多個進程調用accept}else{close(c);//父子進程都要關閉c}} }

運行結果
我們用循環發送的客戶端連接示例:

對應的兩個客戶端發送情況:

總結

以上是生活随笔為你收集整理的socket网络编程——多进程、多线程处理并发的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。