从零编写c++之http服务器(3)-http服务

        http全称超文本传输协议,可调试性高,扩展性也强。上两个篇章我们已经拥有了epoll事件驱动框架和线程池处理网络事件,接下来我们要先写一个基础网络套接字,然后在此基础上扩展出http的套接字。献上类图如下

完整源码见<https://github.com/kwansoner/panda.git>

                                            

        可以看到我们有一个最顶层的基类ISocket,拥有一个方法fd返回描述符,增加这个接口时由于事件中心注册到epoll里需要int型的描述符。接下来在ISocket基础上派生出IServer与IClient两个基类。实例化出两个TCP类型的套接字类CStreamServer与CStreamClient。然后我们就可以组合的方式扩展出两个http套接字类,不用继承的原因是继承增加耦合,也没有必要用继承。由于HttpStream与HttpServer需要收听事件中心的事件回调,因此需要继承IEventHandle。

class ISocket
{
	public:
		virtual ~ISocket(){};
		
		// desc: 获取套接字描述符
		// param: void
		// return: 套接字描述符
		virtual int fd() = 0;
};

class IClient: public ISocket
{
	public:
		virtual ~IClient(){};

		// desc: 打开套接字
		// param: void
		// return: 0/成功 -1/失败
		virtual int start() = 0;

		// desc: 关闭套接字
		// param: void
		// return: 0/成功 -1/失败
		virtual int close() = 0;

		// desc: 设置套接字为非阻塞
		// param: block/是否非阻塞
		// return: 0/成功 -1/失败
		virtual int set_nonblock(bool nonblock) = 0;

		// desc: 连接到server
		// param: addr/server地址 port/端口
		// return: 0/成功 -1/失败
		virtual int connect(const std::string
  • 3
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
编写 HTTP 代理服务器程序可以分为以下几个步骤: 1. 创建套接字并绑定端口 ```c++ #include <sys/socket.h> #include <netinet/in.h> int main() { // 创建套接字 int server_socket = socket(AF_INET, SOCK_STREAM, 0); // 绑定端口 struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = INADDR_ANY; server_address.sin_port = htons(8080); bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)); // 监听端口 listen(server_socket, 5); // 接受客户端连接并处理请求 while (true) { struct sockaddr_in client_address; socklen_t client_address_len = sizeof(client_address); int client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_address_len); // 处理客户端请求 // ... } // 关闭套接字 close(server_socket); return 0; } ``` 2. 接受客户端连接并处理请求 接受客户端连接后,从客户端读取 HTTP 请求报文,解析出目标服务器地址和端口,然后向目标服务器发送 HTTP 请求报文,并将目标服务器响应报文返回给客户端。 ```c++ #include <unistd.h> #include <netdb.h> #include <arpa/inet.h> void handle_request(int client_socket) { // 读取客户端请求报文 char buffer[1024]; int n = read(client_socket, buffer, sizeof(buffer)); buffer[n] = '\0'; // 解析请求报文,获取目标服务器地址和端口 char* host = strstr(buffer, "Host: "); if (host == nullptr) { return; } host += 6; char* end = strchr(host, '\n'); if (end == nullptr) { return; } *end = '\0'; // 连接目标服务器 struct hostent* server = gethostbyname(host); if (server == nullptr) { return; } int server_socket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_address; bzero((char*)&server_address, sizeof(server_address)); server_address.sin_family = AF_INET; bcopy((char*)server->h_addr, (char*)&server_address.sin_addr.s_addr, server->h_length); server_address.sin_port = htons(80); if (connect(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) { return; } // 将请求报文转发给目标服务器 write(server_socket, buffer, strlen(buffer)); // 从目标服务器接收响应报文并转发给客户端 while (true) { n = read(server_socket, buffer, sizeof(buffer)); if (n <= 0) { break; } write(client_socket, buffer, n); } // 关闭套接字 close(server_socket); close(client_socket); } ``` 3. 启动代理服务器 将上面两个步骤的代码组合起来即可实现一个简单的 HTTP 代理服务器。 ```c++ #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <netdb.h> #include <arpa/inet.h> void handle_request(int client_socket) { // ... } int main() { // 创建套接字 int server_socket = socket(AF_INET, SOCK_STREAM, 0); // 绑定端口 struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = INADDR_ANY; server_address.sin_port = htons(8080); bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)); // 监听端口 listen(server_socket, 5); // 接受客户端连接并处理请求 while (true) { struct sockaddr_in client_address; socklen_t client_address_len = sizeof(client_address); int client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_address_len); // 处理客户端请求 handle_request(client_socket); } // 关闭套接字 close(server_socket); return 0; } ``` 以上是一个简单的 HTTP 代理服务器的实现,可以根据需求进行修改和扩展。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值