コード例 #1
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
void channel_handle_client_read(connector_t pconn, int event)
{
    //由于和客户端只有一次交互,不用一直读取
    if (connector_read(pconn, event) > 0)
    {
        char *val = buffer_get_read(pconn->preadbuf);
        message_t pmsg = (message_t)malloc(sizeof(message));
        memset(pmsg, 0, sizeof(pmsg));
        size_t len1 = get_client_msg(val, pmsg);

        if (len1 == 0)
        {
            print_log(LOG_TYPE_ERROR, "Read Client Msg Error %s", val);
            free(pmsg);
            return;
        }

        char data[20] = {0};
        memcpy(data, pmsg->uid, pmsg->len);
        buffer_read(pconn->preadbuf, len1, TRUE);

        memcpy(pconn->uid, data, pmsg->len);

        int len2 = sizeof(connector_t);
        ht_insert(pconn->pworker->pht, data, (pmsg->len)+1, pconn, len2+1);

        context_t pcontext = (context_t)malloc(sizeof(context));
        memset(pcontext, 0, sizeof(context));
        memcpy(pcontext->data, data, pmsg->len);
        list_push_tail(pconn->pworker->plist, pcontext);

        //print_log(LOG_TYPE_DEBUG, "Hash key %s, Len %d", pcontext->data, pmsg->len);

        char cmd[REDIS_CMD_LEN] = {'\0'};
        get_request_str(data, cmd);

        int len = strlen(cmd);

        if (pconn->pworker->redis->state == CONN_STATE_RUN)
        {
            buffer_write(pconn->pworker->redis->pwritebuf, cmd, len);
            connector_write(pconn->pworker->redis);
        }
        else
        {
            print_log(LOG_TYPE_ERROR, "Redis not run");
            list_pop_head(pconn->pworker->plist);
            ht_remove(pconn->pworker->pht, data, (pmsg->len)+1);
            pconn->pworker->neterr_count++;
        }

        free(pmsg);
    }
}
コード例 #2
0
ファイル: net.cpp プロジェクト: 4Second2None/server_src
int connector_write(connector *cr, unsigned short cmd)
{
    unsigned char *msg;
    size_t sz;
    int ret = create_msg(cmd, &msg, &sz);
    if (ret != 0)
        return ret;
    ret = connector_write(cr, msg, sz);
    free(msg);
    return ret;
}
コード例 #3
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
void channel_handle_redis_write(connector_t pconn)
{
    //以非阻塞模式设置套接口,去连接Redis,Epoll返回写通知事件,可能是有数据也可能是连接状态的返回。
    //通过con的state判断是哪种情况,通过调用getsockopt来查看返回的连接状态(连接成功和失败都会返回可写通知)
    if (pconn->state == CONN_STATE_CONNECTING || pconn->state == CONN_STATE_CLOSED)
    {
        connect_redis_done(pconn);
    }
    else
    {
        connector_unsig_write(pconn);
        connector_write(pconn);
    }
}
コード例 #4
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
void channel_handle_redis_read(connector_t pconn, int event)
{
    //修复一个问题,Redis返回的数据已经读取到了缓冲区,不能只读取一个业务包
    if (connector_read(pconn, event) > 0)
    {
        while (buffer_readable(pconn->preadbuf) > 0)
        {
            char *origin = buffer_get_read(pconn->preadbuf);
            char analyse[100] = {0};
            int originlen = get_analyse_data(origin, analyse);

            if (originlen == 0)
            {
                print_log(LOG_TYPE_DEBUG, "buffer no value");
                break;
            }

            buffer_read(pconn->preadbuf, originlen, TRUE);

            if (strcmp(analyse, REDIS_HBVAL) == 0)
                return;

            context_t pcontext = (context_t)pconn->pworker->plist->head->value;
            //print_log(LOG_TYPE_DEBUG, "Redis Read %s List Head Uid %s", analyse, pcontext->data);

            char key[UID_MAX_LEN] = {0};
            memcpy(key, pcontext->data, strlen(pcontext->data));
            MEM_FREE(pcontext);
            list_pop_head(pconn->pworker->plist);

            size_t len1 = strlen(key);
            size_t len2 = 0;
            connector_t pclientcon = (connector_t)ht_get(pconn->pworker->pht, key, len1+1, &len2);

            if (pclientcon)
            {
                ht_remove(pconn->pworker->pht, key, len1+1);

                char val[100] = {0};
                get_response_str(val, key, analyse);
                size_t size = strlen(val);

                buffer_write(pclientcon->pwritebuf, val, size);
                connector_write(pclientcon);
            }
        }
    }
}
コード例 #5
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
static void reids_heartbeat(connector_t pconredis)
{
    struct timeval tm_now;
    gettimeofday(&tm_now, NULL);

    if ((tm_now.tv_sec - pconredis->pworker->ticktime) < REDIS_IDLETIME)
        return;

    pconredis->pworker->ticktime  = tm_now.tv_sec;

    char *key = REDIS_HBKEY;
    char cmd[REDIS_CMD_LEN] = {0};

    if (make_cmd(cmd, REDIS_CMD_LEN, 2, "get", key) < 0)
    {
        print_log(LOG_TYPE_ERROR, "get %s error, file = %s, line = %d", key, __FILE__, __LINE__);
        return;
    }

    int len = strlen(cmd);
    buffer_write(pconredis->pwritebuf, cmd, len);
    connector_write(pconredis);
}
コード例 #6
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
void channel_handle_client_write(connector_t pconn)
{
    connector_unsig_write(pconn);
    connector_write(pconn);
}
コード例 #7
0
ファイル: worker.c プロジェクト: jarrodcal/Backend-Server
//这种异步非阻塞的模式,带来高性能的同时需要开设空间保存还在等待异步返回的数据,如:redis回调的顺序链表,保存connector的哈希表
void * worker_loop(void *param)
{
    worker_t pworker = (worker_t)param;
    pworker->tid = pthread_self();

    int nfds = 0;
    int timeout = 100;
    struct epoll_event evs[4096];
    connector_t pconn = NULL;
    int i;

    while (1)
    {
        nfds = epoll_wait(pworker->epfd, evs, 4096, timeout);

        if (nfds == -1)
        {
            if (errno == EINTR)
                continue;

            print_log(LOG_TYPE_ERROR, "worker epoll_wait error, epfd = %d, errno = %d", pworker->epfd, errno);
            break;
        }

        for (i = 0; i < nfds; i++)
        {
            pconn = (connector_t)evs[i].data.ptr;

            if (evs[i].events & EPOLLIN)
            {
                worker_handle_read(pconn, evs[i].events);
            }
            if (evs[i].events & EPOLLOUT)
            {
                worker_handle_write(pconn);
            }
            if ((evs[i].events & EPOLLERR) || (evs[i].events & EPOLLHUP))
            {
                print_log(LOG_TYPE_DEBUG, "EPOLLERR Or EPOLLHUP Event Occure");
                pworker->neterr_count++;

                connector_close(pconn);
            }
            if (evs[i].events & EPOLLRDHUP)
            {
                connector_unsig_read(pconn);
                connector_unsig_rdhup(pconn);

                //可以在应用层面(写缓冲区)检查数据是否已经完全发出,server发出去,系统层面会在close后根据SO_LINGER的设置处理
                print_log(LOG_TYPE_DEBUG, "EPOLLRDHUP Event Occure");
                pworker->closed_count++;

                if (buffer_readable(pconn->pwritebuf) > 0)
                    connector_write(pconn);
                else
                    connector_close(pconn);
            }

        }

        handle_time_check(pworker);
    }

    return NULL;
}