计算机网络Ⅱ
张淼
计算机学院
多进程并发服务器
父进程主要用于获取客户端连接(不与客户端直接
通信)
对于新的连接fork一个新的子进程进行处理
父子进程避免使用对方的socket
多进程并发服务器
#include
pid_t fork(void);
Returns: 0 in child, process ID of child in parent, -1 on error
对于fork
子进程复制父进程的所有进程内存到其内存地址空间
中。父、子进程的“数据段”,“堆栈段”和“代码
段”完全相同,即子进程中的每一个字节都和父进程
一样
子进程的当前工作目录等环境变量和父进程相同,
fork之前父进程打开的文件描述符,在子进程中同样
打开
子进程拥有自己的进程ID
程序的并发版本
int main(int argc, char *argv[]) {
fork();
printf("Hello! ");
return 0;
}
输出:
Hello!
Hello!
程序的并发版本
int main(int argc, char *argv[]) {
int pid; 输出:
if ((pid = fork()) < 0) { Hello!
Hello fork!
printf("fork err!");
exit(1);
} else if (pid == 0) {
printf("Hello fork! ");
} else {
printf("Hello! ");
}
return 0;
}
// 生成用于接收客户端连接的被动 socket
多进程并发服务器
s = passiveTcp(service, QLEN);
while (1) {
// 接受一个新的连接,套接字描述符 ss
alen = sizeof(fsin);
ss = accept(s, (struct sockaddr *)&fsin, &alen);
// 对于新连接,产生子进程进行处理
if ((pid = fork()) == 0) { // 子进程
// 关闭对父进程socket的引用
close(s);
// 处理业务逻辑
tcpEcho (ss);
exit(0);
} else { // 父进程
// 关闭对子进程socket的引用
close(ss);
}
}
多进程并发服务器状态图
服务器 客户
listenfd 连接请求 connect()函数
客户/ 服务器状态图(调用accept 函数时)
多进程并发服务器状态图(cont. )
服务器 客户
listenfd connect()函数
connfd
客户/ 服务器状态图(调用accept 函数后)
多进程并发