skynet源码阅读<2>--网络部分

    先来看下socket_server的数据结构,这里简称为ss:

 1 struct socket_server {
 2     int recvctrl_fd;
 3     int sendctrl_fd;
 4     int checkctrl;
 5     poll_fd event_fd;
 6     int alloc_id;
 7     int event_n;
 8     int event_index;
 9     struct socket_object_interface soi;
10     struct event ev[MAX_EVENT];
11     struct socket slot[MAX_SOCKET];
12     char buffer[MAX_INFO];
13     uint8_t udpbuffer[MAX_UDP_PACKAGE];
14     fd_set rfds;
15 };

我绘了一张简图,表述网络收发部分的处理流程,如下:

  

    1)skynet启动时会创建单独的socket线程,在这个线程中,通过skynet-socket-poll轮循管道server-pipe。ss.sendctrl_fd是管道的写端,而ss.recvctrl_fd则是管道的读端。

    2)lua-socket.c封装了一组接口,在lua-service中调用这些接口实现socket相关的处理。在调用这些接口时,实现中首先拿到与skynet-context-id,接着构建参数,然后通过ss.sendctrl_fd写入管道。

    3)socket_server_poll中在select管道读端ss.recvctrl_fd时,收到命令后通过skynet-context-id找到关联的socket,再做相应处理,比如listen,accept,或是写入数据到缓存并找到socket关联的事件,打上或关闭write标记等。

    4)另一方面,在socket_server_poll中也会检查event_fd是否有新的事件到来,比如可写时将缓存中数据写出等;处理完这波事件后才会检查下一波事件(sp_wait)。ss.event_n,ss.event_index,ss.ev就是做这些事的。在处理相关事件时,根据需要,会将消息(比如接收到的数据块)打包发送给socket关联的skynet-context,最后回调到lua-service中来。

    其它一些具体的细节,比如epoll或是kqueue模型的使用等,请自行查阅文档。下一篇会以gate为例,揭示在网络处理在lua中的运行和操作流程。

posted on 2017-02-22 14:44  莫行  阅读(782)  评论(0编辑  收藏  举报

导航