多进程并发服务器
多进程并发服务器:server.c
1. Socket(); 创建 监听套接字 lfd
2. Bind() 绑定地址结构 Strcut scokaddr_in addr;
3. Listen();
4. while (1) {
cfd = Accpet(); 接收客户端连接请求。
pid = fork();
if (pid == 0){ 子进程 read(cfd) --- 小-》大 --- write(cfd)
close(lfd) 关闭用于建立连接的套接字 lfd
read()
小--大
write()
} else if (pid > 0) {
close(cfd); 关闭用于与客户端通信的套接字 cfd
contiue;
}
}
5. 子进程:
close(lfd)
read()
小--大
write()
父进程:
close(cfd);
注册信号捕捉函数: SIGCHLD
在回调函数中, 完成子进程回收
while (waitpid());
server.c
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "wrap.h"
#define SRV_PORT 9999
void catch_child(int signum)
{
while ((waitpid(0, NULL, WNOHANG)) > 0);
return ;
}
int main(int argc, char *argv[])
{
int lfd, cfd;
pid_t pid;
struct sockaddr_in srv_addr, clt_addr;
socklen_t clt_addr_len;
char buf[BUFSIZ];
int ret, i;
bzero(&srv_addr, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(SRV_PORT);
srv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
lfd = Socket(AF_INET, SOCK_STREAM, 0);
Bind(lfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
Listen(lfd, 128);
clt_addr_len = sizeof(clt_addr);
while (1) {
cfd = Accept(lfd, (struct sockaddr *)&clt_addr, &clt_addr_len);
pid = fork();
if (pid < 0) {
perr_exit("fork error");
} else if (pid == 0) {
close(lfd);
break;
} else {
struct sigaction act;
act.sa_handler = catch_child;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
ret = sigaction(SIGCHLD, &act, NULL);
if (ret != 0) {
perr_exit("sigaction error");
}
close(cfd);
continue;
}
}
if (pid == 0) {
for (;;) {
ret = Read(cfd, buf, sizeof(buf));
if (ret == 0) {
close(cfd);
exit(1);
}
for (i = 0; i < ret; i++)
buf[i] = toupper(buf[i]);
write(cfd, buf, ret);
write(STDOUT_FILENO, buf, ret);
}
}
return 0;
}
多线程服务器
多线程并发服务器: server.c
1. Socket(); 创建 监听套接字 lfd
2. Bind() 绑定地址结构 Strcut scokaddr_in addr;
3. Listen();
4. while (1) {
cfd = Accept(lfd, );
pthread_create(&tid, NULL, tfn, (void *)cfd);
pthread_detach(tid);
}
5. 子线程:
void *tfn(void *arg)
{
read(cfd)
小--大
write(cfd)
pthread_exit((void *)10);
}
server.c
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "wrap.h"
#define MAXLINE 8192
#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];
while (1) {
n = Read(ts->connfd, buf, MAXLINE);
if (n == 0) {
printf("the client %d closed...\n", ts->connfd);
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(STDOUT_FILENO, buf, n);
Write(ts->connfd, buf, n);
}
Close(ts->connfd);
return (void *)0;
}
int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
pthread_t tid;
struct s_info ts[256];
int i = 0;
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, 128);
printf("Accepting client connect ...\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, do_work, (void*)&ts[i]);
pthread_detach(tid);
i++;
}
return 0;
}