TCP服务器实现-start函数启动过程--多进程模式reactor事件处理过程

版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/81267594

结合上面几篇的分析,我们已经知道了reactor的主事件处理过程和在reactor上面注册的回调逻辑,这篇我们开始分析reactor和回调处理的逻辑,看看reactor和worker的交互是如何做的。首先,我们分析的代码如下图所示:

SwooleG.main_reactor->add(SwooleG.main_reactor, pipe_worker, SW_FD_PIPE | SW_EVENT_READ);
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_PIPE, swWorker_onPipeReceive);
SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_WRITE, swReactor_onWrite);

这些代码位于E:\swoole-src-master\src\network\Work.c里面,我们从swWorker_onPipeReceive开始分析。

//从reactor接收到数据,其中reactor为主事件处理器,而event为事件相关的对象
static int swWorker_onPipeReceive(swReactor *reactor, swEvent *event)
{
    swEventData task;//此次交互数据相关信息,后面分析流程中可以看到
    swServer *serv = reactor->ptr;//获取server信息,主要是server里面携带了PHP侧的回调函数
    swFactory *factory = &serv->factory;//获取factory信息
    int ret;

    read_from_pipe:
    if (read(event->fd, &task, sizeof(task)) > 0)//从event->fd中阻塞读取信息,信息存放在task中,从管道中读取,一般情况下可以读到数据。
    {
        ret = swWorker_onTask(factory, &task);//数据给到worker处理,这里给到的task是个完整的task信息,worker可以直接处理
#ifndef SW_WORKER_RECV_AGAIN
        //这里有个大包的处理流程
        if (task.info.type == SW_EVENT_PACKAGE_START)//task的类型做判断,数据是分多部分传输的
#endif
        {
            //没有数据
            if (ret < 0 && errno == EAGAIN)
            {
                return SW_OK;
            }
            else if (ret > 0) //未读取完全,根据worker的处理结果判断
            {
                goto read_from_pipe;
            }
        }
        return ret;
    }
    return SW_ERR;
}
int swWorker_onTask(swFactory *factory, swEventData *task)
{
    swServer *serv = factory->ptr;//获取server对象
    swString *package = NULL;//用于表示请求体信息,不包括头部
    swDgramPacket *header;//用于UDP的,表示包体头部信息

#ifdef SW_USE_OPENSSL
    swConnection *conn;
#endif

    factory->last_from_id = task->info.from_id;//关联相应的ID
    serv->last_session_id = task->info.fd;//关联相应的ID
    swWorker *worker = SwooleWG.worker;//全局变量SwooleWG是对worker进程的抽象
    //标记worker的状态为繁忙中
    worker->status = SW_WORKER_BUSY;

    switch (task->info.type)//开始处理task的类型
    {
    case SW_EVENT_TCP:
    case SW_EVENT_PACKAGE:
        //discard data
        if (swWorker_discard_data(serv, task) == SW_TRUE)
        {
            break;
        }
        do_task:
        {
            worker->request_time = serv->gs->now;
#ifdef SW_BUFFER_RECV_TIME
            serv->last_receive_usec = task->info.time;
#endif
            serv->onReceive(serv, task);
            worker->request_time = 0;
#ifdef SW_BUFFER_RECV_TIME
            serv->last_receive_usec = 0;
#endif
            worker->traced = 0;
            worker->request_count++;
            sw_atomic_fetch_add(&serv->stats->request_count, 1);
        }
        if (task->info.type == SW_EVENT_PACKAGE_END)
        {
            package->length = 0;
        }
        break;

    //chunk package
    case SW_EVENT_PACKAGE_START:
    case SW_EVENT_PACKAGE_END:
        //discard data
        if (swWorker_discard_data(serv, task) == SW_TRUE)
        {
            break;
        }
        package = swWorker_get_buffer(serv, task->info.from_id);
        if (task->info.len > 0)
        {
            //merge data to package buffer
            swString_append_ptr(package, task->data, task->info.len);
        }
        //package end
        if (task->info.type == SW_EVENT_PACKAGE_END)
        {
            goto do_task;
        }
        break;

    case SW_EVENT_UDP:
    case SW_EVENT_UDP6:
    case SW_EVENT_UNIX_DGRAM:
        package = swWorker_get_buffer(serv, task->info.from_id);
        swString_append_ptr(package, task->data, task->info.len);

        if (package->offset == 0)
        {
            header = (swDgramPacket *) package->str;
            package->offset = header->length;
        }

        //one packet
        if (package->offset == package->length - sizeof(swDgramPacket))
        {
            worker->request_count++;
            worker->request_time = serv->gs->now;
#ifdef SW_BUFFER_RECV_TIME
            serv->last_receive_usec = task->info.time;
#endif
            sw_atomic_fetch_add(&serv->stats->request_count, 1);
            serv->onPacket(serv, task);
            worker->request_time = 0;
#ifdef SW_BUFFER_RECV_TIME
            serv->last_receive_usec = 0;
#endif
            worker->traced = 0;
            worker->request_count++;
            swString_clear(package);
        }
        break;

    case SW_EVENT_CLOSE:
#ifdef SW_USE_OPENSSL
        conn = swServer_connection_verify_no_ssl(serv, task->info.fd);
        if (conn && conn->ssl_client_cert.length > 0)
        {
            sw_free(conn->ssl_client_cert.str);
            bzero(&conn->ssl_client_cert, sizeof(conn->ssl_client_cert.str));
        }
#endif
        factory->end(factory, task->info.fd);
        break;

    case SW_EVENT_CONNECT:
#ifdef SW_USE_OPENSSL
        //SSL client certificate
        if (task->info.len > 0)
        {
            conn = swServer_connection_verify_no_ssl(serv, task->info.fd);
            conn->ssl_client_cert.str = sw_strndup(task->data, task->info.len);
            conn->ssl_client_cert.size = conn->ssl_client_cert.length = task->info.len;
        }
#endif
        if (serv->onConnect)
        {
            serv->onConnect(serv, &task->info);
        }
        break;

    case SW_EVENT_BUFFER_FULL:
        if (serv->onBufferFull)
        {
            serv->onBufferFull(serv, &task->info);
        }
        break;

    case SW_EVENT_BUFFER_EMPTY:
        if (serv->onBufferEmpty)
        {
            serv->onBufferEmpty(serv, &task->info);
        }
        break;

    case SW_EVENT_FINISH:
        serv->onFinish(serv, task);
        break;

    case SW_EVENT_PIPE_MESSAGE:
        serv->onPipeMessage(serv, task);
        break;

    default:
        swWarn("[Worker] error event[type=%d]", (int )task->info.type);
        break;
    }

    //worker idle
    worker->status = SW_WORKER_IDLE;

    //maximum number of requests, process will exit.
    if (!SwooleWG.run_always && worker->request_count >= SwooleWG.max_request)
    {
        swWorker_stop();
    }
    return SW_OK;
}

猜你喜欢

转载自blog.csdn.net/u013702678/article/details/81267594