Linux c实现并发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以上时,测试无法通过,待完善。

猜你喜欢

转载自blog.csdn.net/qq_37242224/article/details/83155436