网络通信服务器
N线程对N客户端
原理
SocketServer server(port)
while(true)
client=server.accept()
new Thread(client).start()
Thrad:client
::run()
read(client)
write(client)
if(client.closed())
SocketServer.post(close, client)
事件分发
defineAndType out List<data> // 定义out的类型为List<data> 列表(队列)
define Client[fd,out, time(lastRx, lastWr), List<data> rmsg; ] //定义客户端类型 fd 为socket 文件句柄, out为发送队列, time为时间
List<Client> clients //客户端列表
ServerSocket server(port) //Socket服务器初始化
Pollfds.add(server.fd) //Pollfds事件选择器,添加服务器句柄
while(true)
pollfds.setClientfd(clients.fd) //为事件选择器添加所有的客户端句柄
for client->clients
pollfds[client.fd].event = POLLIN //设定此客户端有可读事件
if(client.out.length>0)
pollfds[client.fd].event |= POLLOUT //设定有可写事件
pollfds.poll(timeout) //poll等待句柄列表产生事件, eventv表示poll产生的结果
if(server.fd.eventv == POLLIN) //如果产生输入事件是服务器句柄
client= server.accept() //接受一个客户端
clients.append(client) //将客户端添加到客户端列表
for( client: clients) //遍历客户端
if(client. eventv&POLLIN) //如果客户端有数据上来就读
client.rmsg <- client.read() //从客户端读数据
handleAsync(client, client.rmsg) //异步处理消息
if(client.eventv&POLLOUT) //如果客户端可以写
if(client.out.length ==0)
client.write("心跳"), continue;
client.write(client.out.pop()) //从客户端的输入数据队列中取数据
if(client.eventv&POLLERR)
client.close() //客户端断开了
//发送消息到客户端
func clientout(client, msg)
client.out<-msg
client.pollfds.setevent(EOUT) //发送事件,退出poll等待
##
1>怎么添加心跳? 在 client.out.length>0判断时,判断最后接收数据的时间比较,增加POLLOUT
2>怎么异步发数据?
a,增加一个文件句柄,如pipe(fdR,fdW) ,把fdR添加到 pollfds ,设定为POLLIN
b,想发送数据时 client.out.append(data..);
c, write->fdW 这样poll() 就能返回,则client.out.length>0,就会到其POLLOUT事件下发数据
3>给poll() 添加延时任务,以及自定义事件驱动
struct timeval { tv_sec; tv_usec; } 使用u微妙为单位
当超时后去延时任务列表寻找到时间的 回调函数和回调参数;
##
参考开源库方案
mosquito MQTT服务器的 loop.c
Live555 TaskScheduler.cpp 模型
libwebsockets 模型
java-netty框架