多线程/进程并发服务器
使用多进程并发服务器时需要考虑以下几点
①、父进程最大文件描述符个数
②、系统内创建进程个数
③、进程创建过多是否降低整体服务性能

多进程并发服务器流程:
①、socket() 创建监听套接字
②、bind() 绑定地址结构
③、listen()
④、while(1){
cfd = accept();
pid = fork();
if(pid == 0){ 子进程负责数据交换
close(lfd);
read();
a ==> A
write()
}
else if (pid > 0){ 父进程负责:注册信号捕捉函数(SIGCHLD)
在回调函数中完成子进程的回收
close(cfd);
continue;
}
}
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/wait.h>
/*
实现功能:多线程并发服务器,客户端输入小写,服务器小写转大写
代码时间:2022/3/27/12点33分
*/
#define SERPORT 9010
void catch_child(int signo)
{
if(signo == SIGCHLD)
while((waitpid(0, NULL, WNOHANG)) > 0 );
}
int main(int argc, char *argv[])
{
pid_t pid;
struct sockaddr_in ser_addr, cli_addr;
socklen_t cli_addr_len = sizeof(cli_addr);
bzero(&ser_addr, 0);
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(SERPORT);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
int lfd, cfd;
int i;
int ret;
char buf[BUFSIZ];
lfd = socket(AF_INET, SOCK_STREAM, 0);
bind(lfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
listen(lfd, 128);
while(1) {
cfd = accept(lfd, (struct sockaddr *)&cli_addr, &cli_addr_len);
pid = fork();
if(pid == 0) {
close(lfd);
break;
}else if(pid > 0) {
struct sigaction act, oldact;
act.sa_handler = catch_child;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
ret = sigaction(SIGCHLD, &act, &oldact);
close(cfd);
continue;
}
}
if(pid == 0) {
while(1) {
ret = read(cfd, buf, sizeof(buf));
for(i = 0; i < ret; i++) {
buf[i] = toupper(buf[i]);
}
write(cfd, buf, ret);
write(STDOUT_FILENO, buf, ret);
}
}
return 0;
}
实验结果:

多线程并发服务器流程:
①、socket() 创建监听套接字
②、bind() 绑定地址结构
③、listen()
④、while(1){
cfd = accept();
pthread_create(&tid, NULL, tfn, NULL);
pthread_derach(tid) 设置线程分离 死亡自动回收
子线程仍然负责数据交换
}
代码实现:
#include "wrap.h"
#define SER_PORT 8887
struct s_info {
struct sockaddr_in client_addr;
int cfd;
};
void *tfn(void *arg)
{
int ret, i;
struct s_info *ts = (struct s_info *)arg;
char buf[BUFSIZ];
while(1) {
ret = read(ts->cfd, buf, sizeof(buf));
for(i = 0; i < ret; i++)
buf[i] = toupper(buf[i]);
write(ts->cfd, buf, ret);
write(STDOUT_FILENO, buf, ret);
}
return (void *)0;
}
int main(int argc, char *argv[])
{
int lfd, cfd;
struct s_info ts[256];
socklen_t client_len;
struct sockaddr_in ser_addr, client_addr;
pthread_t tid;
int i = 0;
bzero(&ser_addr, 0);
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(SER_PORT);
ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
lfd = Socket(AF_INET, SOCK_STREAM, 0);
Bind(lfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
Listen(lfd, 128);
printf("----------Accepting client connect-----\n");
client_len = sizeof(client_addr);
while(1) {
cfd = Accept(lfd, (struct sockaddr *)&client_addr, &client_len);
ts[i].client_addr = client_addr;
ts[i].cfd = cfd;
pthread_create(&tid, NULL, tfn, (void *)&ts[i]);
pthread_detach(tid);
i++;
}
return 0;
}
本文介绍了一个多线程并发服务器的设计与实现过程,包括如何使用socket编程建立连接,通过多线程处理客户端请求,以及如何管理和回收子线程。
1426

被折叠的 条评论
为什么被折叠?



