ZBLOG

#include #include // for memset #include // for socket functions and structures #include // for sockaddr_in #include // for close() #include "http_server.h" #include "../cJSON/...

您的代码片段展示了一个基本的HTTP服务器框架,使用C++和POSIX socket编程。代码实现了HttpServer类中的几个主要功能,包括初始化监听socket、接收HTTP请求以及处理连接。以下是一些可能需要改进和注意的地方:

1. usockaddr 结构体

您提到的 usockaddr 似乎是一个自定义结构体,但在标准POSIX socket编程中并不存在该类型。如果您打算使用标准的 sockaddr 结构体,可以直接用它替换:

struct sockaddr_storage usa; // 使用 sockaddr_storage 来支持IPv4和IPv6

2. 错误检查

尽量为每个系统调用(如 setsockopt, bind, listen, accept 等)添加详细的错误处理,以帮助调试。例如,在绑定或监听失败时,打印具体错误信息。

3. Port 参数

Init() 方法中,您将传入的端口参数保存在成员变量 port_ 中,但后续使用的是常量 PORT。建议直接使用传入参数。

4. 在接受连接时线程处理

创建新线程以处理每个连接是合适的,但要确保在线程函数中正确地处理指针。您可以通过适当的方法将文件描述符(conn_fd)封装到一个对象中,并确保其生命周期不会引起数据竞争。

static void* handle_request(void* arg) {
    int conn_fd = reinterpret_cast<int>(arg);
    // 这里可以处理请求...
    close(conn_fd); // 请求处理完毕后关闭文件描述符
    return nullptr;
}

完整示例优化后的代码

以下是修改后的代码片段,结合上述建议:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <pthread.h>
#include "http_server.h"
#include "../cJSON/cJSON.h"

void* handle_request(void* arg) {
    int conn_fd = reinterpret_cast<int>(arg);
    // TODO: 添加请求处理逻辑
    close(conn_fd); // 完成后关闭连接
    return nullptr;
}

void HttpServer::receive_response() {
    fd_set lfdset;
    int maxfd;

    for (;;) {
        FD_ZERO(&lfdset);
        maxfd = -1;
        int conn_fd = -1;

        if (listenfd_ != -1) {
            FD_SET(listenfd_, &lfdset);
            if (listenfd_ > maxfd)
                maxfd = listenfd_;
        }

        if (select(maxfd + 1, &lfdset, nullptr, nullptr, nullptr) < 0) {
            perror("select");
            exit(1);
        }

        struct sockaddr_storage usa; // 更改为sockaddr_storage以支持不同协议族
        socklen_t sz = sizeof(usa);

        if (listenfd_ != -1 && FD_ISSET(listenfd_, &lfdset)) {
            conn_fd = accept(listenfd_, reinterpret_cast<struct sockaddr*>(&usa), &sz);
            if (conn_fd < 0) {
                perror("accept");
                continue; // 出现错误,继续下一轮循环
            }
            
            pthread_t thread;
            if (pthread_create(&thread, nullptr, handle_request, reinterpret_cast<void*>(conn_fd)) != 0) {
                perror("Failed to create thread");
                close(conn_fd); // 确保即使创建线程失败也能关闭连接。
                continue; 
            }
            pthread_detach(thread); // 分离线程以避免内存泄漏 
        }
    }
}

int HttpServer::Init(const int& port) {
    port_ = port;
	struct sockaddr_in srv_addr;
	memset(&srv_addr, 0, sizeof(srv_addr));
	srv_addr.sin_family=AF_INET;
	srv_addr.sin_port=htons(port_);
	srv_addr.sin_addr.s_addr=htonl(INADDR_ANY);

	listenfd_ = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd_ < 0) {
		perror("Socket creation failed");
		return -1;
	}

	int opt = 1; 
	if (setsockopt(listenfd_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
		perror("setsockopt error");
		close(listenfd_);
		return -1;
	}

	if (bind(listenfd_, reinterpret_cast<struct sockaddr*>(&srv_addr), sizeof(srv_addr)) == -1) {
		perror("bind error");
		close(listenfd_);
		return -1;
	}

	if (listen(listenfd_, 128) == -1) {
		perror("listen error");
		close(listenfd_);
		return -1;
	}

	return 0;
}

void HttpServer::SendMessage(const std::string& path, const std::string& body) {
   // TODO: 实现发送消息逻辑,这里留空等待实现。
}

HttpServer::~HttpServer() {
	close(listenfd_);
}

总结

这段代码应该能给你一些启发,让你在实现HTTP服务器时更加顺利。如果有任何特定问题或者想了解更多,请随时询问!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6515

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?