c++实现简单http服务器

2023-05-16

http基于tcp协议的应用层协议,说白了就是写死的自定义协议,代码实现了简单的get请求,打开服务后,可以通过网站访问本地资源,适合新手学习的简单代码,有助于理解get和http报文,很简单

HttpService.h
#ifndef HTTP_SERVICE
#define HTTP_SERVICE


#include <stdio.h>
#include <winsock2.h>
#include <iostream>
 
#pragma comment(lib, "ws2_32.lib")  /* WinSock使用的库函数 */
 
 
/* 定义常量 */
#define HTTP_PORT					 6080		 /* 连接的缺省端口 */
#define HTTP_BUF_SIZE				 1024		 /* 缓冲区的大小 */
#define HTTP_FILENAME_LEN			 999		 /* 文件名长度 */
#define	HTTP_FILEEXTENSION_LEN		 20			//文件后缀长度
#define	HTTP_CMD_LEN				 20			//命令长度


/* 定义文件类型对应的 Content-Type */
struct FileExtension
{
    char * pExtensive;	 /* 文件后缀 */
    char * pType;			/* Content-Type */
};


 


class HttpService
{
public:
		char cRecvBuffer[HTTP_BUF_SIZE];				//缓存请求命令
protected:
		char cRecvFile[HTTP_FILENAME_LEN];				//请求文件
		char cExtensive[HTTP_FILEEXTENSION_LEN];		//文件后缀
		char cHttpCmd[HTTP_CMD_LEN];
		
public:
	HttpService();
	~HttpService();


public:
	void AnalyRecvBuffer();
	void HttpResponse(SOCKET sSocket);
protected:
	void Cmd_Get(SOCKET sSocket);
	void Cmd_Post(SOCKET sSocket);
	char *AnalyExtensive();
};










#endif;




httpService类实现

HttpService.cpp


  
#include "HttpService.h"


char * pHttpHead = "HTTP/1.1 200 OK\r\nDate:%s\r\nServer: ZhaoYueYou's Server \r\n"
    "Accept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: close\r\n"
    "Content-Type: %s\r\n\r\n";
struct FileExtension FileType[] = 
	{
		{"html",    "text/html"  },
		{"gif",     "image/gif"  },
		{"jpeg",    "image/jpeg" },
		{"jpg",     "image/jpeg" },
		{"png",		"image/png"},
		{ "js",		"text/javascript"},
		{"css",		"text/css"},
		{"txt",		"text/plain"},
		{"mp4",		"video/mp4"},
		{ NULL,      NULL        }
	};



HttpService::HttpService()
{
	memset(cRecvBuffer,0,HTTP_BUF_SIZE);
	memset(cRecvFile,0,HTTP_FILENAME_LEN);
	memset(cExtensive,0,HTTP_FILEEXTENSION_LEN);
	memset(cHttpCmd,0,HTTP_CMD_LEN); 
}

HttpService::~HttpService()
{

}

void HttpService::AnalyRecvBuffer()
{
	int nLength = 0;
    char *pBegin;
	char *pEnd;
	char *pFile;
	int	nHeadLen = 0;

 
    /* 查找 URL 的开始位置 */
    pBegin = strchr(cRecvBuffer, ' ');

	nHeadLen =  pBegin-cRecvBuffer;
	if(nHeadLen<HTTP_CMD_LEN && nHeadLen>0)
		  memcpy(cHttpCmd, cRecvBuffer, nHeadLen);
	else
		std::cout<<"命令头长度异常 "<<std::endl;

    pBegin += 1;
         
    /* 查找 URL 的结束位置 */
    pEnd = strchr(pBegin, ' ');
    *pEnd = 0;
 
    pFile = strchr(pBegin, '/');
    nLength = pEnd - pFile;


 
    /* 找到文件名的开始位置 */
    if ((*pFile == '/') || (*pFile == '\\'))
    {
        pFile++;
        nLength--;
    }
    /* 得到文件名 */
    if (nLength > 0 && nLength <HTTP_FILENAME_LEN )
    {
        memcpy(cRecvFile, pFile, nLength);
        cRecvFile[nLength] = 0;
 
        pBegin = strchr(cRecvFile, '.');
		int nExtensiveLen = pEnd-pBegin;
        if (pBegin && nExtensiveLen<HTTP_FILEEXTENSION_LEN)
            strcpy(cExtensive, pBegin + 1);
		else
			std::cout<<"后缀长度异常 "<<std::endl;
    }
	else
		std::cout<<"文件长度异常 "<<std::endl;
}

void HttpService::HttpResponse(SOCKET sSocket)
{
	if(!strcmp(cHttpCmd,"GET"))
		Cmd_Get(sSocket);
	else if(!strcmp(cHttpCmd,"POST"))
		Cmd_Post(sSocket);
	else
	{
		std::cout<<"其他命令 "<<cHttpCmd<<std::endl;
	}

}
void HttpService::Cmd_Get(SOCKET sSocket)
{
	int nHttpHeadLen =0;
	int	nFileLen = 0;
	int nSendLen = 0;
	int nRendLen = 0;
	char cReadBuf[HTTP_FILENAME_LEN] = {0};


	FILE *pFile;
	char *pFileType;
    pFile = fopen(cRecvFile, "rb+"); /* 用二进制格式打开文件 */
    if (pFile == NULL)
    {
        printf("[Web] The file [%s] is not existed\n", cRecvFile);
        return ;
    }
	fseek(pFile, 0, SEEK_END);
    nFileLen = ftell(pFile);
    fseek(pFile, 0, SEEK_SET);

	pFileType = AnalyExtensive();
	if (pFileType == NULL)
    {
        printf("[Web] There is not the related content type\n");
        return ;
    }

	SYSTEMTIME sys;   
	GetLocalTime( &sys );   
	char ptr[40]={0};
	sprintf( ptr,"%4d/%02d/%02d %02d:%02d:%02d.%03d ",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute, sys.wSecond,sys.wMilliseconds,sys.wDayOfWeek);   



	 /* 构造 HTTP 首部,并发送 */
	char HttpHeader[HTTP_FILENAME_LEN]={0};
    nHttpHeadLen = sprintf(HttpHeader, pHttpHead,ptr, nFileLen, pFileType);
    nSendLen = send(sSocket, HttpHeader, nHttpHeadLen, 0);
	std::cout<<HttpHeader<<std::endl;
    //send_len=1;
    if (nSendLen == SOCKET_ERROR)
    {
        fclose(pFile);
        printf("[Web] Fail to send, error = %d\n", WSAGetLastError());
        return ;
    }
 
    do /* 发送文件, HTTP 的消息体 */
    {
        nRendLen = fread(cReadBuf, sizeof(char), HTTP_FILENAME_LEN, pFile);
 
        if (nRendLen > 0)
        {
            nSendLen = send(sSocket, cReadBuf, nRendLen, 0);
            nFileLen -= nRendLen;
        }
    } while ((nRendLen > 0) && (nFileLen > 0));
 
    fclose(pFile);
}
void HttpService::Cmd_Post(SOCKET sSocket)
{
}
char *HttpService::AnalyExtensive()
{
   struct FileExtension *pType;
 
   for (pType = FileType; pType->pExtensive; pType++)
    {
        if (strcmp(pType->pExtensive, cExtensive) == 0)
			return pType->pType;
    }
 
    return NULL;
}

入口 main

 

#include "HttpService.h"


void main()
{
	WSADATA wsa_data;
    SOCKET  srv_soc = 0, acpt_soc;  /* socket 句柄 */
    struct sockaddr_in serv_addr;   /* 服务器地址  */
    struct sockaddr_in from_addr;   /* 客户端地址  */
    unsigned short port = HTTP_PORT;
    int from_len = sizeof(from_addr);
	int result = 0,recv_len = 0;

    WSAStartup(MAKEWORD(2,0), &wsa_data); /* 初始化 WinSock 资源 */
     
    srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */
    if (srv_soc == INVALID_SOCKET)
    {
        printf("[Web] socket() Fails, error = %d\n", WSAGetLastError());
		system("pause");
        return ; 
    }
     
    /* 服务器地址 */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//inet_pton(AF_INET,"180.173.168.61",&serv_addr.sin_addr.s_addr);
 
    result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
    if (result == SOCKET_ERROR) /* 绑定失败 */
    {
        closesocket(srv_soc);
		perror("bind:");
        printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());

		system("pause");
        return ; 
    }
 
    result = listen(srv_soc, SOMAXCONN);
    printf("[Web] The server is running ... ...\n");


	 
    while (1)
    {
        acpt_soc = accept(srv_soc, (struct sockaddr *) &from_addr, &from_len);
        if (acpt_soc == INVALID_SOCKET) /* 接受失败 */
        {
            printf("[Web] Fail to accept, error = %d\n", WSAGetLastError());
			system("pause");
            break; 
        }
       
        printf("[Web] Accepted address:[%s], port:[%d]\n", 
            inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
 
		HttpService hService;
		recv_len = recv(acpt_soc, hService.cRecvBuffer, HTTP_BUF_SIZE, 0);
        if (recv_len == SOCKET_ERROR) /* 接收失败 */
        {
            closesocket(acpt_soc);
            printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());
			system("pause");
            break; 
        }
 
        hService.cRecvBuffer[recv_len] = 0;
		hService.AnalyRecvBuffer();
		hService.HttpResponse(acpt_soc);
		closesocket(acpt_soc);

	}
	closesocket(srv_soc);
    WSACleanup();
    printf("[Web] The server is stopped.\n");
 
    return ;
 
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++实现简单http服务器 的相关文章

  • mac上用VSCode搭建 c++ 工程,用于学习Opengl

    先下载VSCode安装c c 43 43 插件 xff0c 安装微软这个 创建一个文件夹作为项目 xff0c 然后用VSCode打开这个目录在这个文件夹中创建好四个目录 xff0c 分别是src xff0c lib include bin
  • 刷赞与评论

    网站自动刷帖 xff0c 刷赞 xff0c 刷评论等网络推广方式的基本实现 里面的思路有东西
  • 系统复制-快速重装系统

    ubuntu 直接把安装好常用软件和环境的系统打包成镜像 xff0c 用systemback安装 xff0c 便捷很多 之前那种 xff0c ubuntu安装都要好久 xff0c 少说也得20分钟吧 xff0c 之前就是等 xff0c 等它
  • 机器人 控制领域

    机器人 控制领域好像没太有很新很有用的工作 xff0c 还是依据Dynamic Model的Motion Planning更接近于任务层 其实 xff0c 感觉自己喜欢的不是控制 而是motion xff0c motion control
  • 树莓派电压过低 串口数据错误增多

    调试过程中 xff0c 树莓派串口读单片机上传的数据 的程序突然一堆checksum error 换一块满电的LiPo电池就大幅减少了报错 一开始猜测原因 可能是电压过低导致CPU运行慢了 xff08 可能叫做 降频 xff09 xff0c
  • 机器人知识体系

    纲 机电力算控感 知识体系体系各元素特点体系的建立和完善 机电力算控感 知识体系 机械 电子电气 力学 xff08 静力学与动力学分析 流体力学 材料力学等 xff09 计算 xff08 通用计算机和嵌入式计算机 xff09 控制理论 感知
  • OpenCV之imwrite()等基本操作

    参考 xff1a Opencv之imwrite 函数的用处 imwrite 函数用来保存图片 opencv3中的imwrite函数是用来输出图像到文件 xff0c 其声明如下 xff1a CV EXPORTS W bool imwrite
  • 麦克纳姆轮全向移动原理

    什么是麦克纳姆轮 在竞赛机器人和特殊工种机器人中 xff0c 全向移动经常是一个必需的功能 全向移动 意味着可以在平面内做出任意方向平移同时自转的动作 为了实现全向移动 xff0c 一般机器人会使用 全向轮 xff08 Omni Wheel
  • 卡尔曼滤波(KF)与扩展卡尔曼滤波(EKF)的一种理解思路及相应推导(1)

    前言 xff1a 从上个世纪卡尔曼滤波理论被提出 xff0c 卡尔曼滤波在控制论与信息论的连接上做出了卓越的贡献 为了得出准确的下一时刻状态真值 xff0c 我们常常使用卡尔曼滤波 扩展卡尔曼滤波 无迹卡尔曼滤波 粒子滤波等等方法 xff0
  • Qt Cmake添加*.qrc资源文件

    cmake minimum required VERSION 3 5 project Test LANGUAGES CXX 这里 file GLOB RECURSE QRC SOURCE FILES CMAKE CURRENT SOURCE
  • IOS 加载本地HTML

    web qtt以 folder形式添加到项目中 xff0c 注意是蓝色的颜色 创建swift项目 xff0c 写入如下代码 span class token comment span span class token comment Vie
  • C#实现:将十进制数转换为十六进制(含完整源码)

    C 实现 将十进制数转换为十六进制 含完整源码 在C 中 我们可以使用基础数据类型来存储整数值 如int long等 而十进制数是我们最常用的数制 但有些场景下需要将其转换为其它进制 如十六进制 本文将介绍如何使用C 来实现将十进制数转换为
  • 怎样用串口发送结构体-简单协议的封包和解包

    先说解决方案 xff0c 细节和实现代码都放在正文 下位机 xff1a 把结构体拆分成8位的整型数据 xff0c 加上数据包头和包尾 xff0c 然后按顺序单个单个地发出 xff1b 上位机 xff1a 把串口里的数据读取出来 xff0c
  • 计算机网络学习笔记——IP Header Checksum(校验和)的计算方法

    从TCP IP协议看到IP数据报 xff0c 看到Checksum的算法描述 xff0c 不甚了了 The checksum field is the 16 bit one s complement of the one s complem
  • 在Ubuntu18.04中更新指定python版本以及pip

    在Ubuntu18 04中更新指定python版本以及pip 更新指定python版本 xff08 eg python3 8 xff09 xff1a 参考 教你Ubuntu安装python3 7 xff0c 并更新python默认指向 xf
  • 【MATLAB数学建模编程实战】遗传算法求解最短路径(附代码及运行效果)

    欢迎关注 xff0c 本专栏主要更新MATLAB仿真 界面 基础编程 画图 算法 矩阵处理等操作 xff0c 拥有丰富的实例练习代码 xff0c 欢迎订阅该专栏 xff01 xff08 等该专栏建设成熟后将开始收费 xff0c 快快上车吧
  • stm32HAL库 串口接收不定长数据(DMA传输)

    相信大家很多初学者都会遇到串口接收不定长数据的情况 对于初学者可能看着有点难理解 xff0c 多看几遍就好 xff0c 亲测能用 话不多说上菜上菜 xff01 xff01 xff01 xff01 此代码是本人在具体工程应用 xff0c 实测
  • Flask - after_request 和 before_request

    目录 特殊的装饰器多个中间件怎么执行的 特殊的装饰器 64 app before request 在视图函数执行前执行 64 app after request 在视图函数执行后执行 span class token keyword fro
  • VScode 占用cpu风扇狂转, C/C++ IntelliSense Server for Visual Studio Code cpptools.exe占用cpu 30%

    点击下面那个红框中的东西 xff0c 然后选择暂停分析 cpu占用立马降下来了
  • 学习C++中遇到的各种问题

    拷贝构造函数到底是个是什么东西 xff1f 到底什么时候用const xff1f amp 是写在前还是写在后 xff1f 有区别 xff1f 为什么在析构函数中加了delete程序就会卡死 xff1f size t是个什么东西 xff1f

随机推荐

  • 【3D目标检测】稀疏卷积

    稀疏卷积实现部分 先说说实现部分 xff0c 对原理感兴趣的往后看 1 稀疏数据生成 这里的思路主要是先利用np meshgrid和np stack创建出稀疏数据补全后shape大小的点云坐标 xff0c 然后随机取前num points个
  • Unity3D之物体跟随鼠标移动和旋转

    void FixedUpdate if Input GetMouseButton 0 Vector3 aimPos 61 Camera main ScreenToWorldPoint new Vector3 Input mousePosit
  • 【寒武纪】视觉算法MLU220硬件适配(1)

    1 xff0c 环境搭建 xff1a MLU220快速上手指南 寒武纪开发者社区 安装硬件驱动和软件工具链 xff0c 也可以直接使用寒武纪官方开发平台 xff1a 寒武纪开发平台 本地开发安装完工具需要进行一些配置 xff1a 安装后配置
  • 【自动驾驶】second模型训练

    1 xff0c 数据组织 xff1a 训练验证数据生成 xff1a python create data py nuscenes data prep data path 61 NUSCENES TRAINVAL DATASET ROOT v
  • OpenMP入门

    OpenMP 是 Open MultiProcessing 的缩写 可以在 Visual Studio 或者 gcc 中使用 Hello World 把下面的代码保存为 omp cc include lt iostream gt inclu
  • 【蒸馏】PointDistiller: Structured Knowledge DistillationTowards Efficient and Compact 3D Detection

    简述 方法的细节 fT和f S 教师检测器和学生检测器中的特征编码层 AT和AS 抽取的待蒸馏体素或重要性得分最高的点的特征 CT和CS 教师和学生检测特征的通道数 GT和GS 教师和学生检测器的图形特征 该方法基于预先定义的重要度评分 x
  • 【自动驾驶】多传感器感知技术解析

    1 传感器 自动驾驶中的传感器主要用到激光雷达 xff0c 毫米波雷达 xff0c 摄像头 xff0c 超声波 xff0c 优缺点如下 xff1a 1 xff09 激光雷达的测距精度 测距范围及对温度和光照的适应性很强 xff0c 缺点线束
  • 【自动驾驶】单目3D检测M3D-RPN解析与paddle复现

    1 简介 作者提出了一种单个的端到端区域建议网络用于多类别3D目标检测 2D和3D检测任务各自的目标是最终对一个对象的所有实例进行分类 xff0c 而它们在定位目标的维数上是不同的 直观地说 xff0c 我们期望能够利用2D检测的强大功能来
  • 【模型压缩】实例分析量化原理

    1 从定点模型训练来分析量化原理 xff1a 定点模型训练是一个迁移训练的过程 xff1a 在浮点网络的相应位置插入定点化处理节点 xff08 相 当于激活函数 xff09 xff0c 然后在这个经过定点化的计算图上重新训练神经网络 以全连
  • 【3D视觉】深度摄像头与3D重建

    1 xff0c Kinect 是微软在2010年6月14日对XBOX360体感周边外设正式发布的名字 大家在上图可以看到 xff0c Kinect两端有两个3D深度摄像头 xff0c 左边那个发射红外线 xff0c 右边那个是一个红外线感应
  • 【3D视觉】realsense D435三维重建

    1 xff0c 硬件 xff1a realsense D435 驱动及SDK开发包安装 GitHub IntelRealSense librealsense Intel RealSense SDK 下载最新驱动 安装后打开 Intel Re
  • ssh: connect to host 10.112.1.5 port 10083: Connection refused

    ssh connect to host 10 112 1 5 port 10083 Connection refused 1 查看已知端口占用情况 我们想知道10083端口的使用情况 xff0c 或者说被谁占用了 xff0c 命令如下 xf
  • Unity之将Texture保存成png

    using UnityEngine using System Collections using System IO public class SaveToPng MonoBehaviour public Shader outShader
  • 基于容器训练OpenPCdet

    基于容器训练OpenPCdet 1 先拉取一个运行的镜像 docker pull djiajun1206 pcdet pytorch1 6 2 基于镜像创建一个容器 nvidia docker run it name pcdet privi
  • 【CUDA入门笔记】概述

    1 xff0c CUDA架构 xff08 1 xff09 一个GPU包含多个多核处理器 xff1b xff08 2 xff09 一个多核处理器包含多个线程处理器 xff08 3 xff09 线程处理器是最基本的计算单元 xff0c 有自己的
  • 【CUDA入门笔记】CUDA内核与线程配置

    1 CUDA核函数 在GPU上调用的函数成为CUDA核函数 Kernel function xff0c 核函数会被GPU上的多个线程执行 每个线程都会执行核函数里的代码 xff0c 当然由于线程编号的不同 xff0c 执行的代码路径可能会有
  • 【CUDA入门笔记】GPU存储结构模型(1)

    GPU存储结构模型 1 CPU可以读写GPU设备中的Global Memory Constant Memory以及Texture Memory内存储的内容 xff1b 主机代码可以把数据传输到设备上 xff0c 也可以从设备中读取数据 xf
  • 【CUDA入门笔记】GPU存储结构模型(2)

    GPU存储结构模型 1 CPU可以读写GPU设备中的Global Memory Constant Memory以及Texture Memory内存储的内容 xff1b 主机代码可以把数据传输到设备上 xff0c 也可以从设备中读取数据 xf
  • 基于多二维码识别的无人机运动真值获取

    基于多二维码识别的三维运动真值获取 1 背景介绍2 原理2 1 二维码基础2 2图像预处理2 3 定位标轮廓提取2 4 多二维码鲁棒识别 3 运行结果3 1对单张图片进行多二维码识别3 2 获取一系列静止图片的轨迹3 3 相机做圆周运动的轨
  • c++实现简单http服务器

    http基于tcp协议的应用层协议 xff0c 说白了就是写死的自定义协议 xff0c 代码实现了简单的get请求 xff0c 打开服务后 xff0c 可以通过网站访问本地资源 xff0c 适合新手学习的简单代码 xff0c 有助于理解ge