并发服务器
Contents
- fork进程
- IO复用
- 线程
多进程
主进程监听,在循环中接受连接请求,当连接建立后,fork一个子进程,在子进程中进行处理。
-
主进程:listen -> while(1) -> accept -> fork -> close connfd
-
子进程:close listenfd -> handle -> close connfd
server:
[root@linuxkit-00155ddc0103 inet]# ./echoserverfork 6667
Parent: waitting…
name[localhost] port[38276]connected! Child No.1 will handle it!
Parent: waitting…
server recived 6 bytes
name[localhost] port[38280]connected! Child No.2 will handle it!
Parent: waitting…
server recived 7 bytes
client1:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
first
first
client2:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
second
second
code
|
|
IO复用
IO复用即使用select函数
#include <sys/select.h>
int select(int n, fd_set *fdset, NULL, NULL, NULL) //等待一组描述符准备好读
FD_ZERO(fd_set *fdset);
FD_CLR(int fd, fd_set *fdset);
FD_SET(int fd, fd_set *fdset);
FD_ISSET(int fd, fd_set *fdset);
stdio与connfd的复用
如果使用echoserver迭代版本的同时,要求能够响应服务器本身的stdin输入,则可以使用select。一个标准输入的fd一般是0,监听fd则是系统分配
- 将stdin和llistenfd加入fdset
- 使用select等待是否有fd准备好
- 通过FD_ISSET查看哪个准备好并进行相应的处理
|
|
server behavior:
[root@linuxkit-00155ddc0103 inet]# ./select 6667
do something
stdin is ready.
do something
hello
stdin is ready.
hello
client connetted.
server recived 12 bytes
ccd //no response here becuse client is connecting
stdin is ready. //client close now
ccd
f
stdin is ready.
f
stdin is ready. //ctrl+D here
client behavior:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
i am client
i am client
基于I/O多路复用的并发事件驱动器
与之前类似,维护一个结构体pool,存储readset,readyset和clientfd
- server监听,初始化pool
- 进入循环,初始化readyset,select阻塞,等待fd准备好
- 若listenfd,添加client
- 对所有准备好的clientfd回射服务
server:
[root@linuxkit-00155ddc0103 inet]# ./echoserverselect 6667
localhost:38334 connected!
Server recived 5 (5 total) bytes on fd 4
Server recived 4 (9 total) bytes on fd 4
Server recived 7 (16 total) bytes on fd 4
localhost:38338 connected!
Server recived 4 (20 total) bytes on fd 5
Server recived 6 (26 total) bytes on fd 5
Server recived 2 (28 total) bytes on fd 5
Close connfd 4
Server recived 7 (35 total) bytes on fd 5
Close connfd 5
client1:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
1234
1234
123
123
123456
123456
[root@linuxkit-00155ddc0103 inet]#
client2:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
123
123
12345
12345
1
1
123456
123456
[root@linuxkit-00155ddc0103 inet]#
code
|
|
多线程
server:
[root@linuxkit-00155ddc0103 inet]# ./echoserverthread 6667
name[localhost] port[38362]connected! Thread id:140562122241792 will serve it!
name[localhost] port[38366]connected! Thread id:140562113849088 will serve it!
server recived 6 bytes from fd 4
server recived 4 bytes from fd 4
server recived 7 bytes from fd 5
server recived 4 bytes from fd 5
client1:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
12345
12345
123
123
client2:
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
654321
654321
321
321
注意传递connfd时是新申请空间,并在thread里释放
code
|
|
基于线程的事件驱动程序
也称作预线程化的方法
- 主线程将连接符connfd放入池中
- 工作线程将connfd取出并处理
- 加入线程和取出线程都使用互斥量保护
- echo程序中的cnt也使用互斥量保护
server
[root@linuxkit-00155ddc0103 inet]# ./echoserver_pre_thread 6667
client[localhost:38376] connected! connfd 4!
server recived 7 (7 total) bytes on fd 4
client[localhost:38380] connected! connfd 5!
server recived 9 (16 total) bytes on fd 5
server recived 4 (20 total) bytes on fd 4
client1
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
123456
123456
123
123
client2
[root@linuxkit-00155ddc0103 inet]# ./echoclient localhost 6667
87654321
87654321
sbuf.c fd池,插入,取出操作
|
|
sbuf结构
|
|
echo_cnt.c
|
|
主程序
|
|
Author lclei
LastMod 2019-07-27