高并发服务器
高并发服务器
并发服务器开发
1.多进程并发服务器 使用多进程并发服务器时要考虑以下几点:
- 父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)
- 系统内创建进程个数(内存大小相关)
- 进程创建过多是否降低整体服务性能(进程调度)
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 8000 void do_sigchild(int num) { waitpid(0, NULL, WNOHANG); } int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int i, n; pid_t pid; struct sigaction newact; 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 %d\n", 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);//若不关长期以往会导致文见文件描述符关闭 return 0; } else if (pid > 0) { Close(connfd); } else perr_exit("fork"); } }
client
#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); } Close(sockfd); return 0; }
2.多线程并发服务器 在使用线程模型开发服务器时需考虑以下问题:
- 调整进程内最大文件描述符上限
- 线程如有共享数据,考虑线程同步
- 服务于客户端线程退出时,退出处理。(退出值,分离态)
- 系统负载,随着链接客户端增加,导致其它线程不能及时得到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 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 been 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 = Accept(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
/* 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, MAXLINE); if (n == 0) printf("the other side has been closed.\n"); else Write(STDOUT_FILENO, buf, n); } Close(sockfd); return 0; }
来源https://www.cnblogs.com/rainbow1122/p/7875702.html
原文地址:https://www.cnblogs.com/zzdbullet/p/9513641.html
时间: 2024-10-08 15:38:42