echo test

client.cpp

#include "co_routine.h"

#include
#include
#include "util.h"
#include
#include
#include
#include
using namespace std;




class STask
{
public:
    stCoRoutine_t *pCo;
    STask(){
        pCo = NULL;
    }
};
int gcount = 0;
int cocount = 10;
STask *arrayTask = NULL;


//#define LOGD(x, ...) printf(x, ##__VA_ARGS__)
#define LOGD(x, ...) (x, ##__VA_ARGS__)
#define LOGI(x, ...) printf(x, ##__VA_ARGS__)


static stack connpool;
void *init_pool(void *p)
{
    co_enable_hook_sys();


    for(int i = 0; i < cocount; i++)
    {
        int fd = socket(AF_INET,SOCK_STREAM,0);
        struct sockaddr_in remote;
        bzero(&remote, sizeof(remote));
        remote.sin_family = AF_INET;
        remote.sin_addr.s_addr = inet_addr("127.0.0.1");
        remote.sin_port = htons(90);

        ::connect(fd, (struct sockaddr *)&remote, sizeof(remote));

        

        connpool.push(fd);
    }
}


void * client(void *arg)
{
    co_enable_hook_sys();


    STask *co = (STask *)arg;


    int fd = 0;
    while(1)
    {
       if(connpool.empty())
            poll(0,0,1);
        if(!connpool.empty())
        {
            fd = connpool.top();
            connpool.pop();
            break;
        }
    }


    int sbuflen = 256;//只能是栈上变量..
    char buf[ sbuflen ];
    char recvb[sbuflen];
    int index = 0;
    for(;;)
    {
        int ret = sprintf(buf, "fd:%d index:%d", fd, index++);
        send(fd, buf, ret + 1, 0);
        int rret = recv(fd, recvb, sizeof(recvb), 0);
        LOGD("%s\n", recvb);
        recvb[0] = 0;
        ++gcount;
    }


    return 0;

}
void * timeout_coroutine(void *priv)
{
    co_enable_hook_sys();
    for (;;)
    {
        poll(0, 0, 1000);//sleep 1s; release cpu...  not yield...


        LOGI("run %d times in 1s\n", gcount);
        gcount = 0;
    }
}


void run()
{
    arrayTask = new STask[2 + cocount];


    co_create(&arrayTask[0].pCo, NULL, init_pool, &arrayTask[0]);
    co_resume(arrayTask[0].pCo);
    for(int i = 1; i < 1 + cocount; i++)
    {
        co_create(&arrayTask[i].pCo, NULL, client, &arrayTask[i]);
        co_resume(arrayTask[i].pCo);
    }


    co_create(&arrayTask[1+cocount].pCo, NULL, timeout_coroutine, &arrayTask[1+cocount]);
    co_resume(arrayTask[1+cocount].pCo);


    co_eventloop(co_get_epoll_ct(), 0, 0);
    LOGD("end of run...\n");
}


int main(int, char *[])
{
    run();
    return 0;
}




server.cpp

#include "co_routine.h"
#include
#include
#include "util.h"
#include
#include
#include
#include
using namespace std;




class STask
{
public:
    stCoRoutine_t *pCo;
    int fd;
    STask(){
        pCo = NULL;
        fd = -1;
    }
};


int cocount = 2;
STask *arrayTask = NULL;


#define LOGD(x, ...) printf(x, ##__VA_ARGS__)
#define LOGI(x, ...) printf(x, ##__VA_ARGS__)


static stack freeco;
void *co_accept(void *p)
{
    co_enable_hook_sys();
    int fd = socket(AF_INET,SOCK_STREAM,0);
    {
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port=htons(90); ///监听端口
        local.sin_addr.s_addr=inet_addr("127.0.0.1");


        ::bind(fd, (struct sockaddr*)&local,sizeof local);
        ::listen(fd, 1024);

        

        SetNonBlock(fd);
    }


    static struct sockaddr_in g_addr;
    socklen_t g_len=0;


    while(1)
    {
        if(freeco.empty())
        {
            poll(0,0,1);
            continue;
        }


         {   //判断是否有新连接
            struct pollfd pf = { 0 };
            pf.fd = fd;
            pf.events = (POLLIN|POLLERR|POLLHUP);
            if(0 == co_poll( co_get_epoll_ct(),&pf,1,3000))
                continue;
        }


       memset(&g_addr,0,sizeof(g_addr));


        //唯独accept没有被hook,所以这里的accept_fd要设成NONBLOCK. 本函数开头已设
        int newfd = accept(fd, (struct sockaddr *)&g_addr, &g_len);
        if( newfd < 0 )
        {
            continue;
        }


        if( freeco.empty() )
        {
            close( newfd );    //协程不够用。。关连接
            LOGD("tcp proc co not enough");
            continue;
        }

        SetNonBlock( newfd );
        STask *co = freeco.top();
        co->fd = newfd;
        freeco.pop();
        co_resume( co->pCo);
    }




    LOGD("co_accept end...\n");
}
void * deal_tcp_routine(void *arg)
{
    co_enable_hook_sys();


    STask *co = (STask *)arg;


    int sbuflen = 256;//只能是栈上变量..
    char buf[ sbuflen ];
    for(;;)
    {
        if(co->fd <= 0)
        {
            freeco.push( co );


            co_yield_ct();
            continue;
        }


        int fd = co->fd;
        sockaddr_in addr;
        if(fd <= 0) assert(0);
        co->fd = -1;


        for(;;)
        {
            struct pollfd pf = { 0 };
            pf.fd = fd;
            pf.events = (POLLIN|POLLERR|POLLHUP);
            int raiseCount = co_poll(co_get_epoll_ct(),&pf,1,1000);

            if(raiseCount == 0) continue; //epoll的socket事件没被激活, 继续epoll


            int ret = read( fd,buf, sizeof(buf));
            if(ret <= 0)
            {
                close(fd);
                break; //会回到外层循环, 然后co->u.fd已被设为-1, 进入队列休眠
            }


            send(fd, buf, ret, 0);
        }
    }


    return 0;
}




void run()
{
    arrayTask = new STask[1 + cocount];


    co_create(&arrayTask[0].pCo, NULL, co_accept, &arrayTask[0]);
    co_resume(arrayTask[0].pCo);
    for(int i = 1; i < 1 + cocount; i++)
    {
        co_create(&arrayTask[i].pCo, NULL, deal_tcp_routine, &arrayTask[i]);
        co_resume(arrayTask[i].pCo);
    }


    co_eventloop(co_get_epoll_ct(), 0, 0);
    LOGD("end of run...\n");
}
void SignalHandler(int nSigno)
{
    switch(nSigno)
    {
    case SIGPIPE:
        LOGI("sigpipe occurred...\n");
        signal(SIGPIPE , &SignalHandler);

    break;
    }
}


int main(int, char *[])
{
    signal(SIGPIPE , &SignalHandler);
    run();
    return 0;
}

你可能感兴趣的:(libco)