实现简易HTTP服务器

简介: 实现简易HTTP服务器

一、套接字接口类封装


#include<iostream>
#include<string>
#include<vector>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
//封装TCPsocket类
#define MAX_LISTEN 5
#define CHECK_RETURN(X) if((X) == false) {return -1;}
class TCPsocket {
  private:
    int _sockfd;
  public:
    TCPsocket () : _sockfd(-1) {}
    //1.创建套接字
    bool Socket() {
      _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      if (_sockfd < 0) {
        perror("create socket error!");
        return false;
      }
      return true;
    } 
    //2.为套接字绑定地址信息
    bool Bind(const std::string &ip, uint16_t port) {
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(port);
      addr.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(struct sockaddr_in);
      int ret = bind(_sockfd, (struct sockaddr*)&addr, len);
      if (ret < 0) {
        perror("bind error!");
        return false;
      }
      return true;
    }
    //客户端:3.向服务器发起连接请求
    bool Connect(const std::string &ip, uint16_t port) {
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(port);
      addr.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(struct sockaddr_in);
      int ret = connect(_sockfd, (struct sockaddr*)&addr, len);
      if (ret < 0) {
        perror("connect error!");
        return false;
      }
      return true;
    }
    //服务端:3.开始监听
    bool Listen(int backlog = MAX_LISTEN) {
      int ret = listen(_sockfd, backlog);
      if (ret < 0) {
        perror("connect error!");
        return false;
      }
      return true;
    }
    //服务端:4. 获取新建连接
    bool Accept(TCPsocket *sock, std::string *ip = NULL, uint16_t *port = NULL) {
      struct sockaddr_in addr;
      socklen_t len = sizeof(struct sockaddr_in);
      int newfd = accept(_sockfd, (struct sockaddr*)&addr, &len);
      if (newfd < 0) {
        perror("accept error!");
        return false;
      }
      sock -> _sockfd = newfd;
      if (ip != NULL) *ip = inet_ntoa(addr.sin_addr);
      if (port != NULL) *port = ntohs(addr.sin_port);
      return true;
    }
    //4. 接收数据
    bool Recve(std::string *body) {
      char temp[8193] = {0};
      int ret = recv(_sockfd, temp, 8192, 0);
      if (ret < 0) {
        perror("recve error!");
        return false;
      }
      else if (ret == 0) {
        std::cout<<"peer shutdown!"<< std::endl;
        return false;
      }
      body -> assign(temp, ret);
      return true;
    }
    //5.发送数据
    bool Send(const std::string &body) {
      int ret = send(_sockfd, body.c_str(), body.size(), 0);
      if (ret < 0) {
        perror("send error!");
        return false;
      }
      return true;
    }
    //6.关闭套接字
    bool Close() {
      if (_sockfd != -1) close(_sockfd);
      return true;
    }
};


二、服务器实现


#include "socket_tcp.hpp"
#include <sstream>
int main(int argc, char *argv[]) {
  if (argc != 2) {
    std::cout<<"./http_server  port"<< std::endl;
    return -1;
  }
  int srv_port = std::stoi(argv[1]);
  std::string srv_ip = "0.0.0.0";
  TCPsocket sock;
  //1.创建套接字
  CHECK_RETURN(sock.Socket());
  //2.绑定地址信息
  CHECK_RETURN(sock.Bind(srv_ip, srv_port));
  //3.开始监听
  CHECK_RETURN(sock.Listen());
  while(1) {
    TCPsocket new_sock;
    bool ret = sock.Accept(&new_sock);
    //4.获取新建连接
    if (ret == false) continue;
    //5.收发数据
    std::string rec;
    new_sock.Recve(&rec);
    size_t pos = rec.find("\r\n\r\n");//查找头部结尾标志
    if (pos == std::string::npos) {
      //没有找到,则认为头部过大
      //将响应状态码设置为414
      //这里简单实现,就直接错误返回了
      return -1;
    }
    std::string header = rec.substr(0,pos);//截取头部
    std::string body = rec.substr(pos + 4);//截取正文
    //正常的截图正文,应该将头部按照\r\n进行分割,逐个取出头部;
    //然后根据头部中的Content-Length确定正文长度,正文长度= rec.size() - header.size() - 4;
    //然后在截取正文
    std::cout<<"header:[" << body << "]" << std::endl;
    std::cout<< "body:[" << body << "]" << std::endl;
    //响应
    std::string rep_body = "<html><body><h1>Hello world!</h1></body></html>";
    std::stringstream ss_reply;
    ss_reply << "HTTP/1.1 200 OK\r\n";
    ss_reply << "Connection: close\r\n";
    ss_reply << "Content-Type: text/html\r\n";
    ss_reply << "Content-Length: " << rep_body.size() << "\r\n";
    ss_reply << "\r\n";
    ss_reply << rep_body;
    std::cout << "response:[" << ss_reply.str() << "]" << std::endl;
    new_sock.Send(ss_reply.str());
    //短连接,完成响应,关闭连接
    new_sock.Close();
  }
  //6.关闭套接字
  sock.Close();
  return 0;
}


三、实现效果


1.运行服务端


1.png


2.在浏览器输入URL进行请求获取响应


 image.png


相关文章
|
24天前
|
搜索推荐 安全 网络安全
服务器支持HTTPS的时机和条件
【10月更文挑战第23天】服务器支持HTTPS的时机和条件
18 5
|
1月前
使用Netty实现文件传输的HTTP服务器和客户端
本文通过详细的代码示例,展示了如何使用Netty框架实现一个文件传输的HTTP服务器和客户端,包括服务端的文件处理和客户端的文件请求与接收。
44 1
使用Netty实现文件传输的HTTP服务器和客户端
|
18天前
|
存储 Oracle 关系型数据库
oracle服务器存储过程中调用http
通过配置权限、创建和调用存储过程,您可以在Oracle数据库中使用UTL_HTTP包发起HTTP请求。这使得Oracle存储过程可以与外部HTTP服务进行交互,从而实现更复杂的数据处理和集成。在实际应用中,根据具体需求调整请求类型和错误处理逻辑,以确保系统的稳定性和可靠性。
20 0
|
2月前
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
143 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
2月前
|
开发者
HTTP状态码是由网页服务器返回的三位数字响应代码,用于表示请求的处理结果和状态
HTTP状态码是由网页服务器返回的三位数字响应代码,用于表示请求的处理结果和状态
32 1
|
3月前
|
缓存 数据安全/隐私保护 UED
代理服务器在HTTP请求中的应用:Ruby实例
代理服务器在HTTP请求中的应用:Ruby实例
|
3月前
|
移动开发 网络协议 编译器
实战案例3:C语言实现的HTTP服务器
实战案例3:C语言实现的HTTP服务器
194 0
|
5天前
|
人工智能 弹性计算 编解码
阿里云GPU云服务器性能、应用场景及收费标准和活动价格参考
GPU云服务器作为阿里云提供的一种高性能计算服务,通过结合GPU与CPU的计算能力,为用户在人工智能、高性能计算等领域提供了强大的支持。其具备覆盖范围广、超强计算能力、网络性能出色等优势,且计费方式灵活多样,能够满足不同用户的需求。目前用户购买阿里云gpu云服务器gn5 规格族(P100-16G)、gn6i 规格族(T4-16G)、gn6v 规格族(V100-16G)有优惠,本文为大家详细介绍阿里云gpu云服务器的相关性能及收费标准与最新活动价格情况,以供参考和选择。
|
10天前
|
机器学习/深度学习 人工智能 弹性计算
什么是阿里云GPU云服务器?GPU服务器优势、使用和租赁费用整理
阿里云GPU云服务器提供强大的GPU算力,适用于深度学习、科学计算、图形可视化和视频处理等多种场景。作为亚太领先的云服务提供商,阿里云的GPU云服务器具备灵活的资源配置、高安全性和易用性,支持多种计费模式,帮助企业高效应对计算密集型任务。
|
12天前
|
存储 分布式计算 固态存储
阿里云2核16G、4核32G、8核64G配置云服务器租用收费标准与活动价格参考
2核16G、8核64G、4核32G配置的云服务器处理器与内存比为1:8,这种配比的云服务器一般适用于数据分析与挖掘,Hadoop、Spark集群和数据库,缓存等内存密集型场景,因此,多为企业级用户选择。目前2核16G配置按量收费最低收费标准为0.54元/小时,按月租用标准收费标准为260.44元/1个月。4核32G配置的阿里云服务器按量收费标准最低为1.08元/小时,按月租用标准收费标准为520.88元/1个月。8核64G配置的阿里云服务器按量收费标准最低为2.17元/小时,按月租用标准收费标准为1041.77元/1个月。本文介绍这些配置的最新租用收费标准与活动价格情况,以供参考。
下一篇
无影云桌面