Linux網絡編程-併發HTTP服務器

github

主要模塊

dataType

1.StringMap

鏈表實現的Map

StringMap* createStringMap ();
void resolvePair (StringMap *map, char *raw, int len, char splitCharacter); 
void resolveMultiPairs (StringMap *map, char *raw, int len, char splitCharacter, char pairSplitCharacter);
void addPair (StringMap *map, char *key, char *value);
char* getValue (StringMap *map, char *key);
void removePair (StringMap *map, char *key);
void outputMap (StringMap *map);
void destroyStringMap (StringMap *map, int freeCompletely);

2.BufList

一個緩衝區鏈表,方便存儲多次socket讀入的數據

BufList* createBufList (int blockSize);
char* addBuf (BufList *bufList);
char* getBuf (BufList *bufList, int index);
void removeBuf (BufList *bufList, int index);
void destroyBufList (BufList *bufList);
char* substractData (BufList *bufList, BufBlockPos start, BufBlockPos end);

threadPool

互斥鎖實現的線程池

ThreadPool* createThreadPool (int maxThreadNum);
void submitTask (ThreadPool *pool, void *(*task) (void *arg), void *arg);
int destroyThreadPool (ThreadPool *pool);

http

http協議實現

1.Request

Request* createRequest ();
Request* substractRequest (int sockFd);
void outputRequest (Request *request);
void destroyRequest (Request *request);

2.Response

Response* createResponse ();
void addHeader (Response *response, char *name, char *value);
void appendContent (Response *response, char *src, int len);
char* serialize (Response *response, int *len);
void destroyResponse (Response *response);

3.Dispatcher

Dispatcher* createDispatcher ();
void registerHandler (Dispatcher *dispatcher, void* (*handler) (Request *, Response *));
void dispatch (Dispatcher *dispatcher, int sockFd);
void destroyDispatcher (Dispatcher *dispatcher);

主要代碼

#define SERVER_IP "0.0.0.0"
#define SERVER_PORT 8000
#define CONCURRENT_NUM 10

ThreadPool *threadPool;
Dispatcher *dispatcher;

// 響應HTTP請求
void* handler (Request *req, Response *rep) {
    rep->statusCode = 200;
    appendContent (rep, "<h1>Hello, World!</h1>", 22);
    return NULL;
}

// 包裝dispatch函數,用作submitTask的參數
void* handlerAdapter (void *arg) {
    int sockFd = *(int*) arg;
    dispatch (dispatcher, sockFd); // 分發給handler處理
    close (sockFd);
    free (arg);
    return NULL;
}

int main(int argn, char **argv) {
    threadPool = createThreadPool (CONCURRENT_NUM);
    dispatcher = createDispatcher ();
    registerHandler (dispatcher, handler); // 註冊HTTP處理器

    int serverFd, connFd, ret;
    socklen_t len;
    char ip[40] = { 0 };
    struct sockaddr_in serverAddr, clientAddr;

	// 創建socket
    serverFd = socket (AF_INET, SOCK_STREAM, 0);
    if (serverFd < 0) {
        printf ("[hyper-server] socket error: %s\n", strerror (errno));
        exit (-1);
    }
    bzero (&serverAddr, sizeof (clientAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons (SERVER_PORT);
    inet_pton(AF_INET, SERVER_IP, &serverAddr.sin_addr);

	// 綁定地址
    ret = bind (serverFd, (struct sockaddr*) &serverAddr, sizeof (serverAddr));
    if (ret != 0) {
        close (serverFd);
        printf ("[hyper-server] bind error: %s\n", strerror (errno));
        exit (-1);
    }

	// 開始監聽
    ret = listen (serverFd, 5);
    if (ret != 0) {
        close (serverFd);
        printf ("[hyper-server] listen error: %s\n", strerror (errno));
        exit (-1);
    }
    printf ("[hyper-server] startup finished on %s:%d\n", SERVER_IP, SERVER_PORT);

    len = sizeof (clientAddr);
    bzero (&clientAddr, sizeof (clientAddr));
    while (TRUE) {
        len = sizeof (clientAddr);
        connFd = accept (serverFd, (struct sockaddr*) &clientAddr, &len);
        printf("[hyper-server] client ip: %s\n", inet_ntop(AF_INET, &clientAddr.sin_addr, ip, sizeof(ip)));
        if (connFd < 0) printf ("[hyper-server] accept error: %s\n", strerror (errno));
        else submitTask (threadPool, handlerAdapter, u_intcpy (connFd)); // 提交任務到線程池,u_intcpy返回一個int指針,指向connFd的一個拷貝
    }
    close (serverFd);

    destroyDispatcher (dispatcher);
    destroyThreadPool (threadPool);
    return 0;
}

性能測試

ab -n 5000 -c 1000 http://localhost:8000/
ab-test
在將測試請求數設置爲7000以上時,測試無法通過,待完善。

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