当前位置: 技术问答>linux和unix
epoll+多线程实现服务器问题
来源: 互联网 发布时间:2017-03-01
本文导语: epoll加多线程想实现一个服务器,看了网上许多epoll的例子,学习了epoll的使用方法,小弟编程不是很好,还有许多问题,所以在这里写出来,希望大家能帮助解答一下,不胜感激。 先说一下,我想实现的功能,epoll...
epoll加多线程想实现一个服务器,看了网上许多epoll的例子,学习了epoll的使用方法,小弟编程不是很好,还有许多问题,所以在这里写出来,希望大家能帮助解答一下,不胜感激。
先说一下,我想实现的功能,epoll监听本地一个端口,若有客户端连接本端口,accept返回客户端的fd,并将此fd加入epoll监听集合,客户端会不断向服务器发送消息,采用tcp协议,服务端收到消息,进行解析,处理,再下发给相应的客户端。
1 epoll监听的事件,可以EPOLLIN与EPOLLOUT同时监听么?
2.客户终端采用tcp协议传输信息,我服务端接收信息应该怎么处理,我epoll使用ET模式,是不是得一次将读写缓冲内的数据都读出来? 消息应该与客户端fd相对应,我是应该存入链表,还是建立一个缓冲池?
3,我想采用多线程的方式去做,但是现在我思路不是很明确,到底这个多线程应该放在epoll监听事件发生分给一个线程来做,还是epoll监听事件发生将其消息读出进行处理的时候用多线程。
好像写的有些混乱,这几天看代码,想流程脑子都乱了 ,大家担待点,小弟底子薄弱,希望大家多给点意见。
先说一下,我想实现的功能,epoll监听本地一个端口,若有客户端连接本端口,accept返回客户端的fd,并将此fd加入epoll监听集合,客户端会不断向服务器发送消息,采用tcp协议,服务端收到消息,进行解析,处理,再下发给相应的客户端。
1 epoll监听的事件,可以EPOLLIN与EPOLLOUT同时监听么?
2.客户终端采用tcp协议传输信息,我服务端接收信息应该怎么处理,我epoll使用ET模式,是不是得一次将读写缓冲内的数据都读出来? 消息应该与客户端fd相对应,我是应该存入链表,还是建立一个缓冲池?
3,我想采用多线程的方式去做,但是现在我思路不是很明确,到底这个多线程应该放在epoll监听事件发生分给一个线程来做,还是epoll监听事件发生将其消息读出进行处理的时候用多线程。
好像写的有些混乱,这几天看代码,想流程脑子都乱了 ,大家担待点,小弟底子薄弱,希望大家多给点意见。
|
1.可以。
2.新手还是不要使用ET模式, ET模式,若一个sockfd(设为非阻塞)变为可读,你就得一直用recv读到出错返回,且errno == EAGAIN为止,, 否则epoll不过再提示你了。 用LTE方式肯定能满足你的要求了。
数据和fd一一对应就得了。 epoll里可以有个epoll_event有个指针的,,指针指向你的数据。 然后当其事件发生时, 将ptr强制转化为你的数据类型(里面包含fd,对应缓冲等等), 然后获得里面的fd , 然后调用合适的函数。 或者epoll_event里面设为fd,每次有事件时,先查找与fd对应的数据 ,再调用相应的函数处理。
3.可以有多种处理方法 。 你是想每个线程对应一个客户连接呢(这种方法不用epoll)? 还是想使用epoll,然后每个事件都开个线程处理呢? 或者使用单线程也行。
对于前者,如果要求不是特别高,不用epoll就可以了。如下:
主线程accept, 得到的fd 开个线程单独处理。 (这种最简单使用了,一对一的,各个线程根据要求,可以采用阻塞,或者非阻塞的方式) ,, 如果每个连接处理时间很短,可以使用线程池。
若是后者的话,就复杂些了。 主线程epoll ,,接收到处理请求,然后开个线程处理。 (除非有某个本地步骤处理时间较长,否则没必要这样做)
2.新手还是不要使用ET模式, ET模式,若一个sockfd(设为非阻塞)变为可读,你就得一直用recv读到出错返回,且errno == EAGAIN为止,, 否则epoll不过再提示你了。 用LTE方式肯定能满足你的要求了。
数据和fd一一对应就得了。 epoll里可以有个epoll_event有个指针的,,指针指向你的数据。 然后当其事件发生时, 将ptr强制转化为你的数据类型(里面包含fd,对应缓冲等等), 然后获得里面的fd , 然后调用合适的函数。 或者epoll_event里面设为fd,每次有事件时,先查找与fd对应的数据 ,再调用相应的函数处理。
3.可以有多种处理方法 。 你是想每个线程对应一个客户连接呢(这种方法不用epoll)? 还是想使用epoll,然后每个事件都开个线程处理呢? 或者使用单线程也行。
对于前者,如果要求不是特别高,不用epoll就可以了。如下:
主线程accept, 得到的fd 开个线程单独处理。 (这种最简单使用了,一对一的,各个线程根据要求,可以采用阻塞,或者非阻塞的方式) ,, 如果每个连接处理时间很短,可以使用线程池。
若是后者的话,就复杂些了。 主线程epoll ,,接收到处理请求,然后开个线程处理。 (除非有某个本地步骤处理时间较长,否则没必要这样做)
|
1 epoll监听的事件,可以EPOLLIN与EPOLLOUT同时监听么?
是可以的,使用epoll_ctl设置即可。
2.客户终端采用tcp协议传输信息,我服务端接收信息应该怎么处理,我epoll使用ET模式,是不是得一次将读写缓冲内的数据都读出来? 消息应该与客户端fd相对应,我是应该存入链表,还是建立一个缓冲池?
1,ET模式需要读到EAGAIN/EWOULDBLOCK再停止。
2,在线列表是一定要维护的,但不是用于映射的,映射直接使用epoll_event内的指针存储对应结构体地址即可,
看到epoll_event.data是一个结构体了吧。
3,我想采用多线程的方式去做,但是现在我思路不是很明确,到底这个多线程应该放在epoll监听事件发生分给一个线程来做,还是epoll监听事件发生将其消息读出进行处理的时候用多线程。
多线程分两种:
1,1线程1客户端
2,1线程N客户端、
对于1:监听线程accept后加入到队列,所有工作线程抢夺队列内的连接。
对于2:监听线程accept后,利用pipe的1字节事件RR派发连接到某一个工作线程(工作线程epoll pipe读事件,每个工作线程一个pipe一个队列)。
是可以的,使用epoll_ctl设置即可。
2.客户终端采用tcp协议传输信息,我服务端接收信息应该怎么处理,我epoll使用ET模式,是不是得一次将读写缓冲内的数据都读出来? 消息应该与客户端fd相对应,我是应该存入链表,还是建立一个缓冲池?
1,ET模式需要读到EAGAIN/EWOULDBLOCK再停止。
2,在线列表是一定要维护的,但不是用于映射的,映射直接使用epoll_event内的指针存储对应结构体地址即可,
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
看到epoll_event.data是一个结构体了吧。
3,我想采用多线程的方式去做,但是现在我思路不是很明确,到底这个多线程应该放在epoll监听事件发生分给一个线程来做,还是epoll监听事件发生将其消息读出进行处理的时候用多线程。
多线程分两种:
1,1线程1客户端
2,1线程N客户端、
对于1:监听线程accept后加入到队列,所有工作线程抢夺队列内的连接。
对于2:监听线程accept后,利用pipe的1字节事件RR派发连接到某一个工作线程(工作线程epoll pipe读事件,每个工作线程一个pipe一个队列)。