2 多线程并发服务器
每个进程可打开的文件描述符数量有限,且进程占用资源较多,系统中进程的数量又受到内存大小的限制,为保证服务器效率,降低服务器消耗,可利用多线程机制搭建并发服务器。
【案例2】搭建多线程并发服务器。
- 服务器端:接收多个客户端的数据,并将接收到的数据转为大写,写回客户端;
- 客户端:向服务器发送数据,并将服务器返回的数据打印到终端。
pthreadServer.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 8000 //端口号
struct s_info {struct sockaddr_in cliaddr;int connfd;
};
//请求处理函数
void *doWork(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 been closed.\n");break;}//of ifprintf("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]);}//of for iWrite(ts->connfd, buf, n);}//of whileClose(ts->connfd);
}//of doWork
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 = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);ts[i].cliaddr = cliaddr;ts[i].connfd = connfd;//创建子线程,处理客户端请求pthread_create(&tid, NULL, doWork, (void*)&ts[i]);i++;}//of whilereturn 0;
}//of mainpthreadClient.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, MAXLINE);if (n == 0){printf("the other side has been closed.\n");}else{Write(STDOUT_FILENO, buf, n);}//of if}//of whileClose(sockfd);return 0;
}//of main