多进程并发服务器
多线程并发服务器
I/O多路转接服务器
epoll的工作模式
在多进程并发服务器中,若有用户请求到达,服务器将会调用fork()函数,创建一个子进程,之后父进程将继续调用accept(),而子进程则去处理用户请求。
【案例1】构建多进程并发服务器。
服务器端:接收多个客户端的数据,并将接收到的数据转为大写,写回客户端;客户端:向服务器发送数据,并将服务器返回的数据打印到终端。forkserver.c
#include
#include
#include
#include
#include "wrap.h"
#define MAXLINE 80 //缓冲数组大小
#define SERV_PORT 8000 //端口号
//子进程回收函数
void doSigChild(int paraNum) {
while (waitpid(0, NULL, WNOHANG) > 0);
} //of doSigChild
int main() {
struct sockaddr_in tempServAddr, tempCliAddr;
socklen_t tempCliAddrLen;
int tempListenFd, tempConnFd;
char tempBuf[MAXLINE];
char tempStr[INET_ADDRSTRLEN];
int i, tempDataLen;
pid_t tempPid;
struct sigaction tempNewAct;
tempNewAct.sa_handler = doSigChild;
sigaction(SIGCHLD, &tempNewAct, NULL); //信号捕获与处理(回收子进程)
tempListenFd = Socket(AF_INET, SOCK_STREAM, 0);
//设置服务器端口地址
bzero(&tempServAddr, sizeof(tempServAddr));
tempServAddr.sin_family = AF_INET;
tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
tempServAddr.sin_port = htons(SERV_PORT);
//使服务器与端口绑定
Bind(tempListenFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
Listen(tempListenFd, 20);
printf("Accepting connections ...\n");
while (1) {
tempCliAddrLen = sizeof(tempCliAddr);
tempConnFd = Accept(tempListenFd, (struct sockaddr *)&tempCliAddr, &tempCliAddrLen);
tempPid = fork(); //创建子进程
if (tempPid == 0) {
//子进程处理客户端请求
Close(tempListenFd);
while (1) {
tempDataLen = Read(tempConnFd, tempBuf, MAXLINE);
if (tempDataLen == 0) {
printf("the other side has been closed.\n");
break;
}//of if
//打印客户端端口信息
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)),
ntohs(tempCliAddr.sin_port));
for (i = 0; i < tempDataLen; i++) {
tempBuf[i] = toupper(tempBuf[i]);
} //of for i
Write(tempConnFd, tempBuf, tempDataLen);
}//of while
Close(tempConnFd);
return 0;
} else if (tempPid > 0) {
Close(tempConnFd);
} else {
perr_exit("fork");
}//of if
}//of while
Close(tempListenFd);
return 0;
}//of main
forkclient.c
#include
#include
#include
#include
#include "wrap.h"
#define MAXLINE 80 //缓冲数组大小
#define SERV_PORT 8000 //端口号
int main() {
struct sockaddr_in tempServAddr;
char tempBuf[MAXLINE];
int tempSockFd, tempDataLen;
tempSockFd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&tempServAddr, sizeof(tempServAddr));
tempServAddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr);
tempServAddr.sin_port = htons(SERV_PORT);
Connect(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));
while (fgets(tempBuf, MAXLINE, stdin) != NULL) {
Write(tempSockFd, tempBuf, strlen(tempBuf));
tempDataLen = Read(tempSockFd, tempBuf, MAXLINE);
if (tempDataLen == 0) {
printf("the other side has been closed.\n");
} else {
Write(STDOUT_FILENO, tempBuf, tempDataLen);
}//of if
}//of while
Close(tempSockFd);
return 0;
} //of main
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)