基於libco、socket、epoll的回射服務器簡單練習

約定:

端口8001

發送socket時先發送一段6字節的消息,表示接下來要發送多少字節的正文,服務器迴應同理(這個機制看上去漏洞百出,好吧,蒟蒻先這麼用着)

client隨便寫一下就好了

server(new.cpp):爲了練習libco、epoll、socket,大概採用這麼一個結構:

主協程負責初始化和eventloop,

有衆多worker協程(個數由宏定義CoNumber限定),worker接收到客戶的fd使用epoll的IO複用完成回射服務器的一套龍服務。worker協程由調度器指揮。

listen協程負責ac請求、將ac後的fd加到ac隊列(鏈表)中,在yield之前調用fd分配器queAcor將隊列中的fd分配給衆多worker,協程由計時器觸發,觸發頻率由AcTimeOut指定,單位ms。

queAcor(fd分配器函數),採用線段樹維護每個worker內部epoll中fd個數,然後將fd分配給工作壓力最小的worker,如果worker因此完成了從沒工作到有工作的轉換,則它會將它在調度隊列中激活。(本來想用二進制優化分配策略,但是想了想還是先不搞這些騷操作了)。前面的之所以用線段樹而不是堆,是因爲堆無法完成非堆頂節點數據的更新(雖然理論上可以這麼做,但是這樣就違背了堆的性質,且寫起來比較麻煩),總之,最後使用的線段樹(雖然它多使用了CoNumber*3*sizeof(int)的內存空間,我覺得還是值的)。

dispatcher協程調度器。由定時器觸發,頻率由DPTTime指定。每調度一次就將所有正在工作的worker遍歷resume一遍,如果當前worker所有客戶都已經下線,則將此worker丟到隊列鏈表後面,下次不觸發,直到它被queAcor激活。

所有協程均使用默認的128kb的棧(沒有使用share stack)

代碼沒有關閉斷言(會影響性能,不過博主沒有測過該代碼的性能)

大概就是這麼一個情況。

至於server(new.cpp)怎麼編譯,見---->>libco配置、編譯 初體驗 - 騰訊協程開源庫

OK,壓縮包版代碼下載見傳送門——>>>https://download.csdn.net/download/greybtfly/10811538

先貼短的client,由於client僅作爲測試用,所以很多地方不嚴謹,比如一些信號沒處理,甚至send都沒循環,見諒。

#include <iostream>
#include<stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<sys/epoll.h>
using namespace std;
int myErrorOperate(char const * const error_str,int error_line,int error_exit=1)
{
    perror(error_str);
    printf("%d\n",error_line);
    if(error_exit==1)
        exit(1);
    return 0;
}

int main()
{
    int serverfd;
    if((serverfd=socket( AF_INET, SOCK_STREAM, 0 ))<0)
        myErrorOperate("socket error ",__LINE__);

    struct sockaddr_in saddr;
    memset ( &saddr, 0, sizeof(saddr) );
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons( 8001 );
    inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);//"118.89.231.196"
    char tmp[900];
    char lenstring[10];
    int ret;
    memset(lenstring,0,sizeof(lenstring));
    int len;
    if(connect(serverfd,(struct sockaddr *)&saddr,sizeof(saddr))<0)
        myErrorOperate("connect err",__LINE__);
    else
    {
        cout<<"success"<<endl;
        while(1)
        {
            cout<<"input----------->";
            cin.getline(tmp,sizeof(tmp));
            if(strcmp(tmp,"exit")==0)
                break;
            int msglen=strlen(tmp)+1;
            sprintf(lenstring,"%d",msglen);
            send(serverfd,lenstring,6,0);
            cout<<"len message sended:"<<lenstring<<endl;
            send(serverfd,tmp,msglen,0);
            len=0;
            cout<<"recving"<<endl;
            while(len<6)
            {
                ret=recv(serverfd,&tmp[len],6-len,0);
                len+=ret;
                if(ret<=0)
                {
                    myErrorOperate("recv len err",__LINE__,1);
                    close(serverfd);
                    return 0;
                }
            }
            int messagelen=atoi(tmp);
            cout<<"recv len message:"<<messagelen<<endl;
            len=0;
            while(len<messagelen)
            {

                ret=recv(serverfd,&tmp[len],messagelen-len,0);
                perror("rcv.");
                len+=ret;
                if(ret<=0)
                {
                    myErrorOperate("recv message err",__LINE__,1);
                    close(serverfd);
                    return 0;
                }
            }
            printf("recv :%d bytes -->%s\n",messagelen,tmp);
            cout<<"a turn complete"<<endl;
        }
    }

    return 0;
}

服務端

#include "co_routine.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <stack>

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>

#include <sys/epoll.h>
#ifdef __FreeBSD__
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>
#endif

#include<iostream>
#include<queue>
#include"co_routine.cpp"
using namespace std;

template<typename dataT>struct link_t;
template<typename dataT>struct linkNode_t;

struct task_t
{
    stCoRoutine_t *co;//協程控制字
    int workNumb;//epoll中的socket個數
    int addNumb;//新來的數目
    link_t<int> *acLink;
    linkNode_t<task_t*> *dptLinkNode;//在調度器鏈表中的位置
    int taskNumb;//協程號
};


template<typename dataT>
struct linkNode_t
{
    struct link_t<dataT> *pLink;
    struct linkNode_t *pNext;
    struct linkNode_t *pPrev;
    dataT data;
};
template<typename dataT>
struct link_t
{
    linkNode_t<dataT> *head;
    linkNode_t<dataT> *tail;
};
typedef struct dpt_t
{
    link_t<task_t*>taskLink;
    int coActivNumb;
}dpt_t;


#define CoNumber 128
#define EpNumber 1024 //一共CoNumber*EpNumber
//#define MinAlloc 100    //協程epoll最小處理個數(如果只有一個worker則不限制)



#define AGAINTIMES 3
#define MSGHeadLen 6
#define MSGBodyLen 1024

int const DPTTime=1;    //調度器調度最小週期,可以調頻
int const AcTimeOut=10;  //socket Ac 頻率

void debug(char const *p)
{
 //  return;
    printf("%s\n",p);
    return;
}

typedef int (*valueFunc_t)(void*,int);
template<int maxSize,valueFunc_t valueFunc> //,size,值計算函數,下標外部從0開始,內部從1開始
class segmentTree
{

    #define lsonrt rt<<1
    #define rsonrt rt<<1|1
    void *ori;//原數組
    int tree[maxSize<<2];
    int ip;
    int value(int idx)
    {
        return (*valueFunc)(ori,idx-1);
    }
    inline void pushup(int rt)
    {
        tree[rt]=min(tree[rt<<1],tree[rt<<1|1]);
    }
public:
    bool empty()
    {
        return !ori;
    }
    void build(int l,int r,int rt)
    {
        if(l==r)
        {
            tree[rt]=value(++ip);
            return;
        }
        build(l,(l+r)>>1,rt<<1);
        build(((l+r)>>1)+1,r,rt<<1|1);
        pushup(rt);
    }
    segmentTree()
    {
        ori=NULL;
        ip=0;
    }
    bool setOri(void *ori)  //注意,ori數組下標從0開始。
    {
        if(ori==NULL)
        {
            debug("segment tree.ori==NULL");
            exit(1);
        }
        if(this->ori)
            return false;
        this->ori=ori;
        ip=0;
        build(1,maxSize,1);
        return true;
    }
    int queryMin()//返回最小值
    {
        if(ori==0)
        {
            cout<<"segmentTree.oir==NULL"<<endl;
            exit(1);
        }
        return tree[1];
    }
    int queryIdx()//返回最小值的下標
    {
        if(ori==NULL)
        {
            cout<<"segmentTree.oir==NULL"<<endl;
            exit(1);
        }
        int rt=1;
        int l=1,r=maxSize;
        while(l<r)
        {
            if(tree[lsonrt]<tree[rsonrt])
            {
                rt=lsonrt;
                r=(l+r)>>1;
            }
            else
            {
                rt=rsonrt;
                l=((l+r)>>1)+1;
            }
        }
        return l-1;
    }
    void update(int idx)
    {
        idx++;

        int rt=1;
        int l=1,r=maxSize;
        int mid;
        while(l<r)  //先找到idx的rt
        {
            mid=(l+r)>>1;
            if(idx<=mid)
            {
                rt=lsonrt;
                r=(l+r)>>1;
            }
            else
            {
                rt=rsonrt;
                l=((l+r)>>1)+1;
            }
        }
        //再遞歸地修改
        tree[rt]=value(l);
        while(rt)
        {
            rt>>=1;
            pushup(rt);
        }
    }
};
int valueFunc(void *arr,int idx)
{
    return ((task_t*)arr)[idx].addNumb+((task_t*)arr)[idx].workNumb;
}
segmentTree<CoNumber,valueFunc>coWoker;
link_t<int> acQue;
task_t _coWoker[CoNumber]={0};//----------------------------------全局變量-----------------
dpt_t dpt;
template<typename T>
void freeLinkNode(T* p)
{
    free(p);
    return;
}
template<typename T>
T* mallocLinkNode()
{
    return (T*)malloc(sizeof(T));
}
template<typename T>
T* callocLinkNode(int n)
{
    return (T*)calloc(n,sizeof(T));
}
int myErrorOperate(char const * const error_str,int error_line,int error_exit=1)
{
    perror(error_str);
    printf("%d\n",error_line);
    if(error_exit==1)
        exit(1);
    return 0;
}
template<typename TLink,typename TNode>
void AddHead(TLink * apLink,TNode *ap)
{
    if(apLink==NULL || ap==NULL)
    {
        myErrorOperate("AddHead.apLink==NULL || ap==NULL",__LINE__,1);
    }
    if(apLink->head)
    {
        apLink->head->pPrev=(TNode*)ap;
        ap->pPrev=NULL;
        ap->pNext=apLink->head;
        apLink->head=ap;
    }
    else
    {
        apLink->head=apLink->tail=ap;
        ap->pNext=ap->pPrev=NULL;
    }
    ap->pLink=apLink;
}

char* mallocMSGBodyMem()
{
    return (char*)malloc(MSGBodyLen);
}
void freeMSGBodyMem(char* p)
{
    free(p);
}


int co_accept(int fd, struct sockaddr *addr, socklen_t *len );

void queAcor()  //將acQue成員分配給worker們
{
    if(acQue.tail==NULL || coWoker.empty())
    {
        return;
    }
    int lst;//空間
    linkNode_t<int> *ptr;
    int i=0;
    for(;acQue.head;)
    {
        if(coWoker.empty())
            break;
        int oldIdx=coWoker.queryIdx();
        task_t *old=&_coWoker[oldIdx];
        if(old->addNumb+old->workNumb==0)
        {
            dpt.coActivNumb++;
        }
        else  if(old->addNumb+old->workNumb==EpNumber)
        {
            myErrorOperate("Acor:too many users err.Refuse connect request.",__LINE__,0);
            ptr=acQue.head;
            RemoveFromLink<linkNode_t<int>,link_t<int>>(ptr);
            close(ptr->data);   //拒絕請求
            freeLinkNode(ptr);
        /*    cout<<"0號協程:" <<_coWoker[0].addNumb+_coWoker[0].workNumb<<endl;
            cout<<"1號協程:" <<_coWoker[1].addNumb+_coWoker[1].workNumb<<endl;
            cout<<"超限協程:" <<old->addNumb+old->workNumb<<endl;
            cout<<"協程號"<<old->taskNumb<<endl;
            cout<<"oldIdx:"<<oldIdx<<endl;
            cout<<"debug ends"<<endl;*/
            break;
        }
        task_t &top=*(old);
        lst=EpNumber - top.workNumb - top.addNumb;
        if(lst>0)
        {
            ptr=acQue.tail;
            for(i=0;i<lst && ptr!=NULL;i++,ptr=acQue.tail)
            {
                RemoveFromLink<linkNode_t<int>,link_t<int>>(ptr);
                AddTail(top.acLink,ptr);
                top.addNumb++;
            }
        }
        linkNode_t<task_t*> *tmp=top.dptLinkNode;
        //在task中加入socket之後,將它在dpt的位置移動到頭部(主要是當它在coLstIdx之後的時候,把它移到前面活躍起來。)
        RemoveFromLink<linkNode_t<task_t*>,link_t<task_t*>>(tmp);
        AddHead(&dpt.taskLink,tmp);
        coWoker.update(oldIdx);
    }
}

static void* dispatcher(void* arg)//協程調度器
{
    static int ActiveCnt=-1;
    task_t *taskQue=(task_t*)arg;
    link_t<task_t*> &link=dpt.taskLink;
    //init
    cout<<"dpt.init"<<endl;
    for(int i=0;i<CoNumber;i++){
        linkNode_t<task_t*> *nodeTmp=mallocLinkNode<linkNode_t<task_t*>>();
        nodeTmp->pLink=NULL;
        nodeTmp->data=&taskQue[i];
        nodeTmp->data->dptLinkNode=nodeTmp;
        AddTail(&link,nodeTmp);
    }
    cout<<"dpt.init.end"<<endl;
    linkNode_t<task_t*> *nodeTmp=NULL;
    for(;;)
    {
        linkNode_t<task_t*> *ptr=link.head;
        if(ptr!=NULL)
        {

            int tmp=dpt.coActivNumb;
      //      cout<<"工作協程號:";
            for(int i=0;ptr && i<tmp;i++)
            {
                if(ptr->data->workNumb+ptr->data->addNumb)//如果這個協程有工作
                {
                    co_resume(ptr->data->co);
         //           cout<<ptr->data->taskNumb<<' ';
                    ptr=ptr->pNext;
                }
                else//沒有工作就把它取出,然後加到後邊
                {
          //          cout<<"沒有工作:"<<ptr->data->taskNumb<<endl;
                  //  dpt.coActivNumb--;
                    nodeTmp=ptr->pNext;
                    RemoveFromLink<linkNode_t<task_t*>,link_t<task_t*>>(ptr);
                    AddTail(&dpt.taskLink,ptr);
                    if(ptr->pNext==nodeTmp && nodeTmp)
                    {
       //                 cout<<nodeTmp<<endl;
                        myErrorOperate("bug****",__LINE__,1);
                    }
                    ptr=nodeTmp;
                }
            }
      //      cout<<endl;
        }
        if(ActiveCnt!=dpt.coActivNumb)
        {
            ActiveCnt=dpt.coActivNumb;
            printf("dispatcher:Active worker numb : %d\n",dpt.coActivNumb);
        }
        struct pollfd pf={0};//不關心epoll時間,只關心時間輪超時事件。
        co_poll(co_get_epoll_ct(),&pf,1,DPTTime);//1ms執行一次
    }
    myErrorOperate("dpt:exit err",__LINE__,1);
}

static void* mcoListen(void *arg_co)
{
    co_enable_hook_sys();
    int lsEpFd;
    lsEpFd=co_epoll_create(128);
    if(lsEpFd<0)
    {
        myErrorOperate("create listen_epfd err",__LINE__);
    }
    int lsSocketFd;
    if((lsSocketFd=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        close(lsEpFd);
        myErrorOperate("create listen_socket fd err.",__LINE__);
    }
    //set socket opt
    int ret,val=1;
    ret=setsockopt(lsSocketFd,SOL_SOCKET,SO_REUSEADDR,(void*)&val,sizeof(val));
    //reuse addr
    if(ret<0)
    {
        myErrorOperate("set SO_REUSEADDR err.",__LINE__,0);
    }
    struct sockaddr_in saddr;
    memset(&saddr,0,sizeof(sockaddr_in));
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr=INADDR_ANY;
    saddr.sin_port=htons(8001);
    ret=bind(lsSocketFd,(struct sockaddr*)&saddr,sizeof(struct sockaddr_in));
    if(ret<0)
    {
        myErrorOperate("lsten socket bind err.",__LINE__,1);
    }
    ret=listen(lsSocketFd,1024);//backlog
    if(ret<0)
    {
        myErrorOperate("listen err.",__LINE__,1);
    }

    socklen_t saddrLen;
    ret=-1;
    for(;;)
    {
        saddrLen=sizeof(saddr);
        ret=co_accept(lsSocketFd,(struct sockaddr*)&saddr,&saddrLen);
       if(ret<0)//每次poll超時後都需要重新加入。
        {
      //      cout<<"acor"<<endl;
            queAcor();//將ac列表中的socket分配給coWoker
      //      cout<<"endAcor"<<endl;
            struct pollfd pf={0};//不關心epoll時間,只關心時間輪超時事件。
            pf.fd=lsSocketFd;
            pf.events=(EPOLLERR|EPOLLHUP|EPOLLIN);
            co_poll(co_get_epoll_ct(),&pf,1,AcTimeOut);//yield   同時關心epoll事件,和1000ms的超時事件
        }
        else if(ret>=0)
        {
            linkNode_t<int> *t=mallocLinkNode<linkNode_t<int>>();
            t->pLink=NULL;
            if(t==NULL)
            {
                close(ret);//若超出了處理範圍則close
                myErrorOperate("socket acQue has too many node.",__LINE__,0);
            }
            t->data=ret;//fd
            AddTail(&acQue,t);
        }
    }
}
void * echoFunc(void *args)
{
    co_enable_hook_sys();
    for(;;)
    {
        cout<<"time 0.5"<<endl;
        struct pollfd pf={0};//不關心epoll時間,只關心時間輪超時事件。
        co_poll(co_get_epoll_ct(),&pf,1,500);//500ms打印一次
    }
}

void workerAddNew(task_t &taskSelf,int epFd)
{
    int ret;
    linkNode_t<int> *ptr=taskSelf.acLink->tail;
    struct epoll_event *ep;
    for(int i=0;i<taskSelf.addNumb;i++)
    {
        ep=mallocLinkNode<struct epoll_event>();
        ep->events=(EPOLLERR | EPOLLIN | EPOLLHUP);
        ep->data.ptr=(void*)ptr;
        ret=epoll_ctl(epFd,EPOLL_CTL_ADD,ptr->data,ep);
        if(ret<0)
        {
            myErrorOperate("worker:epoll_ctl err.",__LINE__,0);
            co_yield_ct();
            i--;
            freeLinkNode(ep);
            continue;
        }
        ptr=ptr->pPrev;
    }
    taskSelf.workNumb+=taskSelf.addNumb;
    taskSelf.addNumb=0;
}
int sendToSocket(int fd,char* buff,int len,bool co=1)
{
    int idx=0;
    int ret;
    int again=AGAINTIMES+1;
    errno=0;
    while(len>idx && again)
    {
        ret=send(fd,buff+idx,len-idx,0);
        if(ret<=0)
        {
            if(errno==EINTR || errno==EAGAIN)
            {
                if(errno==EAGAIN)
                {
                    again--;
                }
                if(co)
                {
                    co_yield_ct();
                }
                continue;
            }
            return ret;
        }
        idx+=ret;
    }
    return len;
}
int recvFromSocket(int fd,char*buff,int len,int line,bool co=1)
{

    memset(buff , 0 , len);
    errno=0;
    int idx=0;
    int ret;
    int again=AGAINTIMES+1;
    while(len>idx && again)
    {
        ret=recv(fd,buff+idx,len-idx,MSG_WAITALL);
     //   perror("rcv form socket:");
        if(ret==0)
        {

        }
        if(ret<=0)
        {
      //      cout<<"ret=="<<ret<<endl;
      //      perror("rcv.");
            if(errno==EINTR || errno==EAGAIN)
            {
     //           cout<<"rcv err"<<errno<<endl;
                if(errno==EAGAIN)
                {
                    again--;
                }
                if(co)
                {
                    co_yield_ct();
                }
                continue;
            }
            return ret;
        }
        idx+=ret;
    }
    if(idx<len || again==0)
    {
        return -1;
    }
    return len;
}
bool checkSocketConnect(task_t &taskSelf,linkNode_t<int>*ptr,int ret,int line)
{
    if(ret<=0)
    {
        if(ret==0)
        {
            debug("client closed");
        }
        else
        {
            debug("client err");
        }
        RemoveFromLink<linkNode_t<int>,link_t<int>>(ptr);
        close(ptr->data);
        freeLinkNode(ptr);
        taskSelf.workNumb--;
        coWoker.update(taskSelf.taskNumb);
        return 1;
    }
    return 0;
}
void *wokerRoutine(void *_coWoker) //系統默認協程棧大小爲128KB
{

    co_enable_hook_sys();
    link_t<int> *linkTmp = mallocLinkNode<link_t<int>>();
    memset(linkTmp,0,sizeof(link_t<int>));
    static struct epoll_event evtOut[EpNumber];//因爲每次運行時協程都會重新取出epoll中active事件,所以此緩衝區可以共享。
    task_t &taskSelf=*(task_t*)((task_t*)_coWoker);
    //接受數據,發送數據。
    int epFd=-1;
    int ret;
    for(;;)
    {
        if(taskSelf.workNumb+taskSelf.addNumb==0)
        {
            co_yield_ct();
            continue;
        }
        if(epFd==-1)
        {
            epFd=epoll_create(100);
            if(epFd<0)
            {
                myErrorOperate("WokerEp epoll_create err.With CoNumber=",__LINE__,0);
                co_yield_ct();
                continue;
            }
        }
        //將新的加入
        workerAddNew(taskSelf,epFd);
        //處理事件
        int activeNumb;
        errno=0;
        activeNumb=epoll_wait(epFd,evtOut,taskSelf.workNumb,0);//這裏的延時時間寫0不知道有沒有問題????????????????????????????????、
        if(activeNumb<0)
        {
            myErrorOperate("epoll_wait err",__LINE__,0);
            co_yield_ct();
            continue;
        }
        char msgHead[MSGHeadLen+1];//如果是static可能會非協程安全。
        msgHead[MSGHeadLen]=0;//結束符
        for(int i=0;i<activeNumb;i++)
        {
            linkNode_t<int> * ptr=(linkNode_t<int> *)evtOut[i].data.ptr;//ptr是workLink中的fd對應節點。該節點data域爲fd
            int sFd=ptr->data;
            int evt=evtOut[i].events;
            if(evt&EPOLLERR || evt&EPOLLHUP )
            {
                if(evt&EPOLLERR)
                {
                    myErrorOperate("user socket err.user exit",__LINE__,0);
                }
                else
                {
                    printf("user exit\n");
                }
                checkSocketConnect(taskSelf,ptr,0,__LINE__);
                continue;
            }
            else if(evt&EPOLLIN)
            {
                int len;
                errno=0;
                ret=recvFromSocket(sFd,msgHead,MSGHeadLen,__LINE__);//讀長度信息
                if(checkSocketConnect(taskSelf,ptr,ret,__LINE__))
                    continue;
                ret=sendToSocket(sFd,msgHead,MSGHeadLen);//發送長度信息
                if(checkSocketConnect(taskSelf,ptr,ret,__LINE__))
                {
                    continue;
                }
                int msgLen=atoi(msgHead);
                char *msgBody=mallocMSGBodyMem();
                len=0;
                int sdLen;
                bool cls=0;
                while(len<msgLen)
                {
                    errno=0;
                    ret=recvFromSocket(sFd,msgBody,min(MSGBodyLen,msgLen-len),__LINE__);//接受一段body信息
                    len+=ret;
                    if(checkSocketConnect(taskSelf,ptr,ret,__LINE__))
                    {
                        cls=1;
                        break;
                    }
                    sdLen=ret;
                    ret=sendToSocket(sFd,msgBody,sdLen);                       //將這一段body發送出去
                    if(checkSocketConnect(taskSelf,ptr,ret,__LINE__))
                    {
                        cls=1;
                        break;
                    }
                }
                if(cls)
                    continue;
            }
            else
            {
                myErrorOperate("unkown err",__LINE__,0);
            }
        }
        if(taskSelf.addNumb+taskSelf.workNumb==0)
        {
            dpt.coActivNumb--;
        }
        co_yield_ct();
    }
    return NULL;
}

void main_init()
{
    acQue.head=acQue.tail=NULL;

    struct sigaction sa;    //這三行:設置向已關閉socket發送信息時默認行爲。防止向已關閉socket發送數據導致服務器崩潰
    sa.sa_handler = SIG_IGN;
    sigaction( SIGPIPE, &sa, 0 );
}
int main() {
    cout<<"服務器初始化..."<<endl;
    main_init();
    task_t coLs,coDpt;
    cout<<"創建調度..."<<endl;
    co_create(&(coDpt.co),NULL,dispatcher,(void*)_coWoker);//init _coWoker.dpt
    link_t<int> *acLinkMem=callocLinkNode<link_t<int>>(CoNumber);
    cout<<"協程池初始化..."<<endl;
    for(int i=0;i<CoNumber;i++)
    {
        _coWoker[i].taskNumb=i;//引用線段樹,協程調度輸出標識
        _coWoker[i].acLink=acLinkMem+i;
        co_create(&(_coWoker[i].co),NULL,wokerRoutine,&_coWoker[i]);
    cout<<i<<endl;
        co_resume(_coWoker[i].co);
    }
    cout<<"segment tree init"<<endl;
    coWoker.setOri((void*)&_coWoker);
    cout<<"創建listen..."<<endl;
    co_create(&(coLs.co),NULL,mcoListen,&coLs);

    cout<<"啓動listen..."<<endl;
    co_resume(coLs.co);//啓動ac
    cout<<"啓動調度..."<<endl;
    co_resume(coDpt.co);

    cout<<"服務器初始化完畢,啓動服務."<<endl;
    co_eventloop(co_get_epoll_ct(),0,0);
    return 0;
}












 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章