首先创建epoll对象,
把要监控的文件描述符添加进去(要指明你要监控这个文件描述符的什么事件,文件描述符添加之前要设置为非阻塞的),
假设我们监控可读事件,
事件到达—说明缓冲区里有数据了,我们可以去读了,
首先我们读出前几个字节,这是我自己约定好的来确定包的总长度,当然也可以定长或者采用特殊结束字段什么的来判断。
用一个循环来读,知道返回值为和等于包长度或者-1(errno为EAGAIN或者EWOULDBLOCK),
(需要特别处理的是,当总长度大于设定的socketbuffer最大值时,我们本次最多只能读到bufferMax这个值,也就说明在本次事件我们不能接完完整的包,我们把这个事件fd和收到的数据放到队列中,另外如果除了包长度之外还有多余的数据怎么处理?会不会出现两个包粘混在一起的情况?)
如果我们获得了完整的包,我先不改变对这个fd的监控,它还是被监控着是否可读,
根据包内容做逻辑处理,确认回包内容后,把回包放到输出队列,改变对这个fd的监控为是否可写,
当监控到fd可写的事件后,从输出队列中取出回包内容,
在一个循环中不断的写直到累计等于要写的包长度或者-1(errno为EAGAIN或者EWOULDBLOCK),
如果本次没写完要改变记录状态,等待该fd的下一次可写事件的发生继续完成写操作,当写完成后,改变对该fd的监控事件为是否可读.
上面这个过程是一个理想过程,包内容逻辑处理可能是一个阻塞的过程,这会带来一系列的问题,如果此时的epoll和这个逻辑处理不在一个线程,那么此时该fd再次收到第二个包数据会发生什么?(如果在一个线程epoll的优势好像就被破坏了)
此外读写需不需要单独到各自的线程中去处理,或者每个fd都分离出各自的独立线程处理读写和回包逻辑?
第一种单独的读一个线程,写一个线程,不断的处理读队列和写队列里的内容,读队列生成buffer事件添加到包事件队列交给回包逻辑线程去处理,处理完生成回包添加到写队列,结构上比较清晰,可以根据负荷调整各部分的线程数目;需要考虑的是读写线程可能的空转比例
第二种每增加一个fd就拉一个线程或者干脆采用线程池,感觉占用的内存资源会多,会大大增加cpu压力,划不划算,主要看回包逻辑复杂程度;
第三种由于这里的读写本来就是非阻塞的所以读写和epoll事件监视循环在一块,epoll的timeout设为0,这种处理少开了线程也少了好几处的资源竞争问题但是感觉总体结构不是太理想。
高频小包,
高频大包,
长间隔包,
长连接,
短连接,
socketbuffer的大小设置,
是否可以采用进程加速扩容,
是否可以多ip扩容,
空闲处理,
线程管理,
回包逻辑是否复杂