当前位置: 首页 > news >正文

使用C++从零开始,自己写一个MiniWeb

第一步:新建项目

1、打开VS点击创建新项目

2、选择空项目并点下一步(切记不能选错项目类型)

3、填写项目名称和路径,点击创建即可

 

新建好后项目是这样的比较干净 

4、右击源文件,点击添加,新建http.cpp文件

第二步:前期准备

在http.cpp最上面引入依赖,并撰写main方法,打印错误日志的方法

#include<stdio.h>
#include<string.h>
#include<WinSock2.h>
#include<sys/types.h>
#include<sys/stat.h>
#pragma comment(lib,"WS2_32.lib")
#define PRINTF(str) printf("[%s - %d]"#str"%s",__func__,__LINE__,str);//打印错误日志
void error_die(const char* str) {perror(str);exit(1);}int main(void) {return 0;
}

第三步:网络初始化

初始化可以分为五步:1、网络通讯初始化===>>>2、创建套接字===>>>3、绑定端口===>>>4、绑定套接字===>>>5、创建监听队列

代码实现如下:

int startup(unsigned short *port) {//1、网络通讯初始化WSADATA data;int res = WSAStartup(MAKEWORD(1,1), &data);if (res) {error_die("init fail");}//2、创建套接字int server_socket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);if (server_socket == -1) {error_die("sock create fail");}//3、绑定端口int opt = 1;res = setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,(const char*) & opt, sizeof(opt));if (res) {error_die("port bing fail");}//4、绑定套接字struct sockaddr_in server_addr;memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(*port);server_addr.sin_addr.s_addr = htonl(INADDR_ANY);res = bind(server_socket,(struct sockaddr*) &server_addr, sizeof(server_addr));if (res<0) {error_die("sock bing fail");}//5、创建监听队列int nameLen = sizeof(server_addr);if (*port == 0) {res = getsockname(server_socket, (struct sockaddr*)&server_addr,&nameLen);if (res) {error_die("dynamic sock create fail");}*port = server_addr.sin_port;}res = listen(server_socket, 5);if (res < 0) {error_die("listen queque create fail");}return server_socket;};

main方法修改如下:

int main(void) {//1、初始化unsigned short port = 8000;int server_sock = startup(&port);printf("http have benn started ,listening [%d] port...",port);return 0;
}

第四步:处理用户请求

1、报文背景知识

浏览器发起新的访问时,会向服务器端发送一个请求报文。例如,在浏览器地址输入 127.0.0.1:8000 回车后,服务器端收到的完整报文如下:

GET / HTTP/1.1\n
Host: 127.0.0.1:8000\n
Connection: keep-alive\n
Cache-Control: max-age=0\n
Upgrade-Insecure-Requests: 1\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\n
Sec-Fetch-Site: none\n
Sec-Fetch-Mode: navigate\n
Sec-Fetch-User: ?1\n
Sec-Fetch-Dest: document\n
Accept-Encoding: gzip, deflate, br\n
Accept-Language: zh-CN,zh;q=0.9\n
\n

请求报文由4四个部分组成:请求行、请求头部行、空行、请求数据。具体格式如下:

2、具体处理

具体处理代码如下:

//从指定的客户端套接字读取一行数据,保持到buff中,返回实际读取到了字节数
int get_line(int sock, char* buff, int size) {char c = 0;int i = 0;while (i < size - 1 && c != '\n') {int n = recv(sock, &c, 1, 0);if (n > 0) {if (c == '\r') {n = recv(sock, &c, 1, MSG_PEEK);if (n > 0 && c == '\n') {recv(sock, &c, 1, 0);}else {c = '\n';}}buff[i++] = c;}else {c = '\n';}}buff[i] = 0;return 0;
}//向指定套接字,发送一个未支持提示还没有实现的错误页面
void unimplement(int client) {char buf[1024];sprintf(buf, "HTTP/1.0 501 Method Not Implemented\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, SERVER_STRING);send(client, buf, strlen(buf), 0);sprintf(buf, "Content-Type: text/html\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "<HTML><HEAD><TITLE>Method Not Implemented\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "</TITLE></HEAD>\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "<BODY><P>HTTP request method not supported.\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "</BODY></HTML>\r\n");send(client, buf, strlen(buf), 0);}//向指定套接字,发送一个未支持提示还没有实现的错误页面
void not_found(int client) {char buf[1024];sprintf(buf, "HTTP/1.0 404 NOT FOUND\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, SERVER_STRING);send(client, buf, strlen(buf), 0);sprintf(buf, "Content-Type: text/html\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "<HTML><TITLE>Not Found</TITLE>\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "<BODY><P>The server could not fulfill\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "your request because the resource specified\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "is unavailable or nonexistent.\r\n");send(client, buf, strlen(buf), 0);sprintf(buf, "</BODY></HTML>\r\n");send(client, buf, strlen(buf), 0);}//发送响应的头信息
void headers(int client) {char buff[1024];strcpy(buff, "HTTP/1.0 200 OK\r\n");send(client, buff, strlen(buff), 0);strcpy(buff, "Server:MyHttpd/0.1\r\n");send(client, buff, strlen(buff), 0);strcpy(buff, "Content-type:text/html\n");send(client, buff, strlen(buff), 0);strcpy(buff, "\r\n");send(client, buff, strlen(buff), 0);}//发送文件
void cat(int client,FILE* resource) {char buff[4096];int count = 0;while (1) {int ret = fread(buff, sizeof(char), sizeof(buff), resource);if (ret <= 0) {break;}send(client, buff, ret, 0);count += ret;}printf("total send [%d] to client\n",count);
}void server_file(int client,const char* fileName) {char numchars = 1;char buff[1024];while (numchars > 0 && strcmp(buff, "/n")) {numchars = get_line(client, buff, sizeof(buff));PRINTF(buff);}FILE*  resource = fopen(fileName,"r");if (resource==NULL) {not_found(client);}else {//发送头信息headers(client);//发送文件cat(client, resource);printf("file send success");}fclose(resource);}DWORD WINAPI accept_request(LPVOID arg) {char buff[1024];int client = (SOCKET)arg;//1、获取第一行int numchars = get_line(client, buff,sizeof(buff));PRINTF(buff);char method[255];int j = 0 ,i =0;while (!isspace(buff[j])&&i < sizeof(method)-1) {method[i++] = buff[j++];}method[i] = 0;PRINTF(method);//2、检查请求方法是否支持if (stricmp(method,"GET")&& stricmp(method, "POST")) {//向浏览器返回错误提示页面unimplement(client);return 0;}//3、解析资源路径char url[255];i = 0;while (isspace(buff[j]) && j < sizeof(buff)) {j++;}while (!isspace(buff[j])&& sizeof(url)-1 && j < sizeof(buff)) {url[i++] = buff[j++];}url[i] = 0;PRINTF(url);char path[512] = "";sprintf(path, "htdocs%s", url);if (path[strlen(path)-1]=='/') {strcat(path, "index.html");}PRINTF(path);struct stat status ;if (stat(path,&status)==-1) {//把请求包里的东西读完while (numchars>0&&strcmp(buff,"/n")) {numchars = get_line(client, buff, sizeof(buff));}PRINTF(buff);not_found(client);}else {if ((status.st_mode & S_IFMT)==S_IFDIR) {strcat(path, "index.html");}server_file(client,path);}closesocket(client);return 0;
}

github地址:

https://github.com/1756336885/miniWeb.git

gitee地址:

miniWeb: 迷你版的web,用C++撰写,后期会添加数据库,中间件相关的操作

参考文章:

2-创建项目_哔哩哔哩_bilibili

C语言手写HTTPD网站服务器_126775241csdn-CSDN博客

相关文章:

使用C++从零开始,自己写一个MiniWeb

第一步&#xff1a;新建项目 1、打开VS点击创建新项目 2、选择空项目并点下一步&#xff08;切记不能选错项目类型&#xff09; 3、填写项目名称和路径&#xff0c;点击创建即可 新建好后项目是这样的比较干净 4、右击源文件&#xff0c;点击添加&#xff0c;新建http.cpp文件…...

Android Graphics 图像显示系统 - 开篇

“ 随着学习的不断深入和工作经验的积累&#xff0c;欲将之前在博客中整理的Android Graphics知识做进一步整理&#xff0c;并纠正一些理解上的错误&#xff0c;故开设Graphics主题系列文章 ” 序言 由于工作需要&#xff0c;也源于个人兴趣&#xff0c;终于下决心花时间整理一…...

机器学习在各个行业的应用介绍

随着科技的飞速发展&#xff0c;机器学习已经从实验室走向了现实世界&#xff0c;逐渐成为各行各业不可或缺的工具。从金融领域到医疗健康&#xff0c;从零售市场到制造业&#xff0c;机器学习正在改变着我们的工作方式和生活质量。 本文将深入探讨机器学习在以下几个领域的应用…...

【生产实测有效】Windows命令行查看激活状态脚本

Windows查看激活状态关键代码 通过windows server 自带的PowerShell来执行 Get-WmiObject SoftwareLicensingProduct | Select-Object -Property Description, LicenseStatus | findstr "Operating System"|findstr "1$"Get-WmiObject SoftwareLicensingPr…...

简单的Udp服务器

目录 简单的UDP网络程序1.1 UdpServer.hpp1.2 UdpClient.cc1.3 main.cc1.4 makefile1.5 log.hpp 简单的UDP网络程序 1.1 UdpServer.hpp #pragma once#include <iostream> using namespace std;#include <unistd.h> #include <sys/types.h> #include <sy…...

【Linux进程间通信】用管道实现简单的进程池、命名管道

【Linux进程间通信】用管道实现简单的进程池、命名管道 目录 【Linux进程间通信】用管道实现简单的进程池、命名管道为什么要实现进程池&#xff1f;代码实现命名管道创建一个命名管道 理解命名管道匿名管道与命名管道的区别命名管道的打开规则 作者&#xff1a;爱写代码的刚子…...

Linux操作系统基础(九):Linux用户与权限

文章目录 Linux用户与权限 一、文件权限概述 二、终端命令&#xff1a;组管理 三、终端命令&#xff1a;用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…...

蓝桥杯——第 5 场 小白入门赛(c++详解!!!)

文章目录 1 十二生肖基本思路&#xff1a; 2 欢迎参加福建省大学生程序设计竞赛基本思路&#xff1a;代码&#xff1a; 3 匹配二元组的数量基本思路&#xff1a;代码: 4 元素交换基本思路&#xff1a;代码&#xff1a; 5 下棋的贝贝基本思路&#xff1a;代码&#xff1a; 6 方程…...

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量&#xff0c;叶节点满足&#xff0c;从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现&#xff0c;当不满足条件时直接返回。 到达叶节点后统计答案&#xff0c;用…...

797. 差分

Problem: 797. 差分 文章目录 思路解题方法复杂度Code 思路 这是一个差分数组的问题。差分数组的主要适用场景是频繁对原始数组的某一个区间进行增减操作。这种操作是区间修改操作&#xff0c;在这种操作下&#xff0c;差分数组只需要对区间的两个端点进行操作&#xff0c;时间…...

2024.2.5 vscode连不上虚拟机,始终waiting for server log

昨天还好好的&#xff0c;吃着火锅&#xff0c;做着毕设&#xff0c;突然就被vscode给劫了。 起初&#xff0c;哥们跟着网上教程有模有样地删除了安装包缓存&#xff0c;还删除了.vscode-server&#xff0c;发现没卵用&#xff0c;之前都是搜那个弹窗报错。 后来发现原来是vsco…...

CSS基础---新手入门级详解

CSS:层叠样式表 CSS&#xff08;Cascading Style Sheets,层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档添加样式&#xff08;字体、间距和颜色&#xff09;的计算机语言&#xff0c;css扩展名为.css。 实例: <!DOCTYPE html><html> <head><…...

Python中Pymysql库的常见用法和代码示例

关注B站可以观看更多实战教学视频&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) pymysql是一个用于连接MySQL数据库的Python库&#xff0c;它允许你执行SQL查询并处理返回的结果。以下是pymysql库的一些常见用法和代码示例&#xff1a; 1. 安装…...

使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序

对于在线客服与营销系统&#xff0c;客服端指的是后台提供服务的客服或营销人员&#xff0c;他们使用客服程序在后台观察网站的被访情况&#xff0c;开展营销活动或提供客户服务。在本篇文章中&#xff0c;我将详细介绍如何通过 WPF Chrome 内核的方式实现复合客服端应用程序。…...

fastapi mysql 开发restful 3

pip install mysql-connector-python pymysql 数据库链接 创建src目录&#xff0c;里面创建db.py 代码如下&#xff1a; # 导入mysql.connector模块&#xff0c;该模块提供了与MySQL数据库进行连接和交互的功能。 import mysql.connector # 定义一个函数get_db_connectio…...

【Uniapp uni-app学习与快速上手——详细讲解】

Uniapp uni-app学习与快速上手——详细讲解 1. 介绍2. Uni-app 学习资源3. 快速上手4. 开始第一个项目5. 调试和发布 1. 介绍 Uni-app 是一个使用 Vue.js 编写多端应用的前端框架。开发者可以编写一份代码&#xff0c;然后发布到iOS、Android、网页&#xff08;响应式&#xf…...

剑指offer——旋转数组的最小数字

目录 1. 题目描述2. 分析思路2.1 示例分析 3. 更完美的做法 1. 题目描述 把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;我们称之为数组的旋转。输入一个递增排序的数组的一个旋转&#xff0c;输出旋转数组的最小元素。例如数组{3.4,5,1.2}为{1.2,3,4,5}的一个旋转&a…...

盘点数据可视化大屏焦点图十种样式

所谓焦点图就是大屏中居于中心位置的图&#xff0c;是视觉的中心&#xff0c;本位列举了十种焦点图样式供大家参考。 地球作为焦点图 图片来自网络 地图作为焦点图 图片来自网络 城市作为焦点图 图片来自网络 园区做焦点图 图片来自网络 建筑做焦点图 图片来自网络 生产线…...

问题 G: 老鼠和猫的交易

题目描述 小老鼠准备了M磅的猫粮&#xff0c;准备去和看守仓库的猫做交易&#xff0c;因为仓库里有小老鼠喜欢吃的五香豆。 仓库有N个房间&#xff1b; 第i个房间有J[i] 磅的五香豆&#xff0c;并且需要用F[i]磅的猫粮去交换&#xff1b; 老鼠不必交换该房间所有的五香豆&…...

HiveSQL——借助聚合函数与case when行转列

一、条件函数 if 条件函数 if函数是最常用到的条件函数&#xff0c;其写法是if(xn,a,b), xn代表判断条件&#xff0c;如果xn时&#xff0c;那么结果返回a ,否则返回b。 selectif(age < 25 or age is null, 25岁以下, 25岁以上) as age_cnt,count(1) as number from table…...

使用swoole作为MQTT客户端并接收实现即时消息推送

环境准备 首先需要安装swoole 可以使用pecl进行安装 &#xff0c;如 pecl install swool, 注意加上版本号 或者使用构建好的docker镜像&#xff0c;这里使用构建好的 zacksleo/php:7.1-alpine-fpm-swoole 镜像 使用 compose 安装依赖库 composer require jesusslim/mqttcl…...

VibePlayer

源代码地址&#xff1a; VibePlayer: VibePlayer是一款功能强大的Android音乐播放器应用&#xff0c;专为音乐爱好者设计&#xff0c;提供了丰富的音乐播放和管理功能。 用户需求 VibePlayer是一款功能强大的Android音乐播放器应用&#xff0c;专为音乐爱好者设计&#xff0…...

【RAG召回】bge实现向量相似度索引

sentence-transformers 是一个非常强大的 Python 框架&#xff0c;它可以将句子或段落转换成高质量、高信息密度的数字向量&#xff08;称为“嵌入”或 Embeddings&#xff09;。它厉害的地方在于&#xff0c;语义上相似的句子&#xff0c;其向量在空间中的距离也更近。 这使得…...

从 ClickHouse、Druid、Kylin 到 Doris:网易云音乐 PB 级实时分析平台降本增效

网易云音乐基于 Apache Doris 替换了早期架构中 Kylin、Druid、Clickhouse、Elasticsearch、HBase 等引擎&#xff0c;统一了实时分析架构&#xff0c;并广泛应用于广告实时数仓、日志平台和会员报表分析等典型场景中&#xff0c;带来导入性能提升 3&#xff5e;30 倍&#xff…...

将单体架构项目拆分成微服务时的两种工程结构

一.独立Project 1.示意图 此时我们创建一个文件夹&#xff0c;在这个文件夹中&#xff0c;创建N个Project&#xff0c;每一个Project对应一个微服务&#xff0c;组成我们的最终的项目。 2.特点 适合那种超大型项目&#xff0c;比如淘宝&#xff0c;但管理负担比较重。 二.Mave…...

day 18进行聚类,进而推断出每个簇的实际含义

浙大疏锦行 对聚类的结果根据具体的特征进行解释&#xff0c;进而推断出每个簇的实际含义 两种思路&#xff1a; 你最开始聚类的时候&#xff0c;就选择了你想最后用来确定簇含义的特征&#xff0c; 最开始用全部特征来聚类&#xff0c;把其余特征作为 x&#xff0c;聚类得到…...

Android 集成 Firebase 指南

Firebase 是 Google 提供的一套移动开发平台&#xff0c;包含分析、认证、数据库、消息推送等多种服务。以下是在 Android 应用中集成 Firebase 的详细步骤&#xff1a; 1. 准备工作 安装 Android Studio - 确保使用最新版本 创建或打开 Android 项目 - 项目需要配置正确的包…...

力扣HOT100之二分查找:4. 寻找两个正序数组的中位数

这道题如果没有时间复杂度的限制的话&#xff0c;相当好做&#xff0c;但是这道题要求时间复杂度为O(log(m n))&#xff0c;思路很难想&#xff0c;我看了一圈题解&#xff0c;发现华南溜达虎的视频讲得还不错&#xff0c;我是参考他的思路写出来的&#xff0c;这里把他的思路…...

在 Conda 环境下配置 Jupyter Notebook 环境和工作目录

作为数据科学家或Python开发者&#xff0c;Jupyter Notebook 是我们日常工作的得力工具。本文将详细介绍如何在 Conda 环境中配置 Jupyter Notebook&#xff0c;包括环境设置和工作目录管理&#xff0c;帮助你打造高效的工作流程。 为什么要在 Conda 环境中使用 Jupyter Noteb…...

【八股消消乐】如何解决SQL线上死锁事故

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本专栏《八股消消乐》旨在记录个人所背的八股文&#xff0c;包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点&#xff…...