1. 程式人生 > >socket程式設計多執行緒模型

socket程式設計多執行緒模型

/*問題
1.調整程序內的最大檔案描述符上限
2.執行緒如有共享資料,考慮執行緒同步
3.服務與客戶端執行緒退出時,退出處理
4.系統負載,隨著連結客戶端增加,導致其他執行緒不能及時得到CPU
*/

/*server.c*/
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arp/inet.h>
#include <pthread.h>
#include "wrap.h"//自己封裝socket出錯處理函式,可檢視本部落格文件

#define MAXLINE 80
#define SERV_PORT 8000
struct s_info{
	struct sockaddr_in cliaddr;
	int connfd;
};

void* do_work(void* arg)
{
	int n, i;
	struct s_info* ts = (struct s_info*)arg;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN];

	/*可以在建立執行緒前設定執行緒建立屬性,設為分離態*/
	/*也可以利用函式設定分離態*/
	pthread_detach(pthread_self());

	while(1){
		n=Read(ts->connfd,buf, MAXLINE);
		if(n==0){
			printf("the other side has benn closed.\n");
			break;
		}
		printf("received from %s at PORT %d\n", 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);
}

int main(void)
{
	struct sockaddr_in servaddr, cliaddr;
	socklen_t cliaddr_len;
	int listenfd, connfd;
	int i=0;
	pthread_t tid;
	struct s_info ts[383];

	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 = Accepting(listenfd, (struct sockaddr*)&cliaddr, &cliaddr_len);
		ts[i].cliaddr = cliaddr;
		ts[i].connfd = connfd;
		/*達到執行緒最大數時,pthread_create出錯處理,增加伺服器穩定性*/
		pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
		i++;
	}
	return 0;
}

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char* argv[])
{
	struct sockaddr_in servaddr;
	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, strlen(buf));
		if(n == 0)
			printf("the other side has been closed.\n");
		else
			Write(STDOUT_FILENO, buf, n);
	}
	Close(sockfd);
	return 0;
}