之前的程式,都是一個 connect 一個 thread , 在連線不多情況下還 ok , 但是萬一

需要處理上千個 connection ?  例如 , clients 透過 socket 來取得 行情 ,  此時, 你的

server 可能 處理一千個連線, 這些連線絕大部分是 recv 行情資料 , 小部份是 send 所要取得行情的股票代碼!!

 

方法是使用 epoll ,  我測試  epoll 最不習慣的地方在於, 如果你的程式需要 clients 先送上四碼代表資料長度,

後面再送上真正的資料,由於 tcp/ip 是 stream-based protocal , 所以就算是那四碼都有可能被分成兩次封包傳送 !!

一個 connect 一個 thread 的  程式,只要使用 之前我寫的介面,直到收到整整四個 bytes再return 的 function 即可 ,

然而 , epoll 這種 event-driven 程式 , 對於處理這種資料流傳一半的情況要花多點時間,且容易有 bug ,

使用 libevent library 這問題變的非常容易解決 , 先看一段程式碼 :

 

void read_cb(struct bufferevent *bev, void *arg)
{
    char record[256] ;
    int idy,n;
    evutil_socket_t fd = bufferevent_getfd(bev);
    struct evbuffer *input = bufferevent_get_input(bev);
    int ifieldwidth = 0 ;
    ifieldwidth = sizeof(DataFeedClient[0].ordid[0])  ; //"|" included
    while(1)
    {
        size_t len = evbuffer_get_length(input);
        //printf("fd=(%u),len=(%d)\n",fd,len) ;
        size_t leftlen = len ;
        while(1)
        {
            if(leftlen >= ifieldwidth)
            {
                evbuffer_copyout(input, record, ifieldwidth);
                record[ifieldwidth-1]=0x00 ; //take off "|"
                //printf("(%s)\n",record) ;
                evbuffer_drain(input,ifieldwidth);
                leftlen = leftlen - ifieldwidth ;

                if(strncmp(record,"START",5)==0)
                {
                    ++DataFeedClient[fd].seqno1 ;
                    DataFeedClient[fd].fillarridx = 0 ;
                    for(idy=0;idy<MAXORDID;idy++){
                        memset(DataFeedClient[fd].ordid[idy],0x00,
                        sizeof(DataFeedClient[0].ordid[0]) ) ;
                    }//for
                }
                else if(strncmp(record,"END",3)==0)
                {
                    ++DataFeedClient[fd].seqno2 ;
                    printdatafeed(fd) ;
                }else{
                    if(DataFeedClient[fd].fillarridx <= (MAXORDID -1) )
                    strcpy(DataFeedClient[fd].ordid[DataFeedClient[fd].fillarridx],record) ;
                    ++DataFeedClient[fd].fillarridx ;
                }

            }else //if
                break ;
        }//while
        break ;

    }
    //printf("out of while \n") ;
}

 

你只要每次都去 get_length , 未滿 4 就跳出 , 滿四的話,不先取出來,例如這四碼是 "0100" , 表示資料長度是 100 ,

所以直到 get_length >= 104 , 才將資料取出 , 這樣處理方便太多了 !!!

 

copyout 是將資料 copy 出來 , drain 把資料給從 buffer 刪除 ,  libevent 在 buffer 處理比起自己使用 epoll 處理每個

connect buffer 實在容易的多了 !!!

 

 

 

arrow
arrow
    全站熱搜

    hedgezzz 發表在 痞客邦 留言(0) 人氣()