1. 程式人生 > >C/S模式下---多執行緒程式設計

C/S模式下---多執行緒程式設計

伺服器採用單程序/執行緒程式設計,在同一時刻,伺服器只能與一個客戶端進行互動。只有與當前客戶端的通訊結束後,才能為下一個客戶端進行服務。所以,如果採用執行緒,讓主執行緒連線客戶端,而函式執行緒為每個客戶端進行服務,這樣就可以保證伺服器可以同時為多個客戶端提供服務,實現併發。

採用多執行緒的優勢
1.執行緒佔用資源少。
2.從CPU的工作角度上看,執行緒的切換速度要比程序快。
3.資源共享,執行緒之間的通訊更加簡單。
4.編碼實現相對簡單。

程式碼:ser.c

#include <sys/scoket.h>
#include <arpa/inet>  
#include <netinet/in.h>
#include <assert.h>
#Include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

void* fun(void* arg){
	int c = (int)arg;
	char buff[128] = {0};
	while(1){
		int n = recv(c,buff,127,0);
		if(n<=0){
			printf("client quit!\n");
			close(c);
			break;
		}
		printf("%d : %s",c,buff);
		send(c,"OK",2,0);
	}
	pthread_exit(NULL);
}

int main(){
	int fd = socket(AF_INET,SOCK_STREAM,0);
	assert(fd!=-1);
	struct sockaddr_in cli,ser;
	ser.sin_family = AF_INET;
	ser.sin_port = htons(6000);
	ser.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	int res = binf(fd,(struct sockaddr*)&ser,sizeof(ser));
	assert(res!=-1);
	
	res = listen(fd,5);
	assert(res!=-1);

	while(1){
		socklen_t len = sizeof(cli);
		int c = accept(fd,(struct sockaddr*)&cli,&len);
		if(c==-1){
			printf("link error!\n");
			continue;
		}
		pthread_t id;
		pthread_create(&id,NULL,fun,(void*)c);//值傳遞,不能地址傳遞
	}
	close(fd);
	return 0;
}

執行結果:
在這裡插入圖片描述
檢視執行緒數量:
在這裡插入圖片描述
需要注意的問題:
在向函式執行緒傳遞檔案描述符的引數必須以值傳遞的形式進行傳遞,因為程序中的各個執行緒共享程序的PCB,如果以傳地址或傳引用的形式傳輸檔案描述符,之前的正在被服務的客戶端檔案描述符可能被修改造成程式出錯。

採用伺服器端多執行緒程式設計的缺點:
1.要考慮執行緒安全問題。
2.執行緒之間不是相互獨立的。
3.程序中的棧幀的大小是有限的,只能啟動有限個數的執行緒。