Linux網絡編程-併發HTTP服務器
主要模塊
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/
在將測試請求數設置爲7000以上時,測試無法通過,待完善。