#include #include #include #include #include #include #include #include "errno.h" #include "tools/log/log.h" #include "http_rel.h" #include int write_in_bk(char input,httpbuf* blk){ if(blk->size%HTTP_BLOCK_SIZE == 0)//块满分配新块 { void *tes = realloc(blk->buf,blk->size+HTTP_BLOCK_SIZE); if(tes = NULL){//无法分配内存,清理并返回NULL free(blk->buf); perror("http rec error"); return -1; } blk->buf = tes; } blk->buf[blk->size] = input; blk->size++; return 0; } char *recv_http_request(int cfd){ httpbuf buf; buf.buf = NULL; // cppcheck-suppress missingReturn buf.buf = (char*)malloc(HTTP_BLOCK_SIZE); char input; for(;;) { read(cfd,&input,1); switch(input){//截取头部 case '\n': if(buf.buf[buf.size-1] == '\r'&&buf.buf[buf.size-2] =='n'&&buf.buf[buf.size-3] == '\r') { buf.size-3; buf.buf = (char*)realloc(buf.buf,buf.size);//截取头部 goto HEAD_RCV;//跳转到头部解析 } else { if(write_in_bk(input,&buf)==-1) abort(); break; } default: if(write_in_bk(input,&buf)==-1) abort();//缓存头部 break; } } HEAD_RCV: //获取http体长度 char length[MAX_HTTP_LENGTH] = {' '}; int index = buf.size-1; int tobewrite = MAX_HTTP_LENGTH-1; while(buf.buf[index]!=' ') { length[tobewrite] = buf.buf[index]; index--;tobewrite--; } int bodylength = atoi(length); free(buf.buf);//释放头部 buf.buf = malloc(bodylength); read(cfd,buf.buf,bodylength); return buf.buf; } /** * @brief 初始化HTTP监听socket,所有错误通过logmanager记录 * @param port 监听端口 * @param logger 日志管理器实例指针 * @return 成功返回监听fd,失败返回-1并记录日志 */ int init_http_network(int port, log_manager *logger) { logs *log; int fd; /* 1. 创建socket */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { log = malloc(sizeof(logs)); // cppcheck-suppress uninitdata snprintf(log->log, sizeof(log->log), "[FATAL] socket() failed: %s", strerror(errno)); logger->in_log(log, logger); return -1; } /* 2. 设置SO_REUSEADDR,避免TIME_WAIT状态导致bind失败 */ int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] setsockopt(SO_REUSEADDR) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 3. 设置为非阻塞模式(配合epoll使用) */ int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] fcntl(F_GETFL) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[ERROR] fcntl(O_NONBLOCK) on fd=%d failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 4. 绑定到指定端口 */ struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); // 监听所有网卡 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[FATAL] bind(port %d) failed: %s (fd=%d)", port, strerror(errno), fd); logger->in_log(log, logger); close(fd); return -1; } /* 5. 开始监听 */ if (listen(fd, 10) == -1) { log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[FATAL] listen(fd=%d, backlog=10) failed: %s", fd, strerror(errno)); logger->in_log(log, logger); close(fd); return -1; } /* 6. 成功日志 */ log = malloc(sizeof(logs)); snprintf(log->log, sizeof(log->log), "[HTTP] Successfully listening on port %d (fd=%d)", port, fd); logger->in_log(log, logger); return fd; }