HTTP协议详解 - 通过C++实现HTTP服务剖析HTTP协议

2023-05-16

前言

  • C/C++程序员一般很少会接触到HTTP服务端的东西,所以对HTTP的理解一般停留在理论。 本文章实现通过C++实现了一个http服务,可以通过代码对HTTP协议有更深的理解,并且通过抓包工具对HTTP协议进行更为详细的分析。

HTTP协议简介

  • HTTP(hypertext transport protocol 超文本传输协议):一种无状态的,以请求/应答方式运行的协议,它使用可扩展的语义和自描述消息格式,与基于网络的超文本信息系统灵活的互动。

HTTP报文格式

  • 请求报文:由请求行,头部字段集合,消息正文三大部分组成。
    请添加图片描述

    • 请求行:描述请求的基本信息

      • 请求方法
        • 请求方法说明
          GET请求服务器发送某个资源
          POST用来传输实体的主体
          PUT用来传输文件
          HEAD获取报文首部,用于确认URI的有效性及资源更新的日期时间等
          DELETE删除文件
          OPTIONS查询针对请求URI指定的资源支持的方法
          TRACE用于追踪路径
          CONNECT要求与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信
      • URI:统一资源标识符(Uniform Resource Identifier)
      • HTTP版本
        • HTTP版本说明
          HTTP/0.91991年制定,只支持GET方法
          HTTP/1.01996年诞生,增加了POST,HEAD方法
          HTTP/1.11999年发布并成为标准,增加了PUT方法,并允许持久连接
    • 头部字段集合:使用key-value形式更详细地说明报文。主要分为四类:通用首部,请求首部,响应首部,实体首部

      • 通用首部:提供与报文相关的基本信息。既可以出现在请求报文中,也可以出现在响应报文中。
        • 首部字段名说明
          CacheControl控制缓存的行为
          Connection允许客户端和服务端指定与请求/响应连接有关的选项
          Date创建报文的日期时间
          Pragma另一种随报文传送指示的方式,但并不专用于缓存
          Transfer-Encoding告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式
          Trailer报文末端的首部一览
          Update给出了发送端可能想要"升级"使用的新版本或协议
          Via显示了报文经过的中间节点(代理,网关)
      • 请求首部:只在请求报文中有意义的首部。用于说明是谁或什么在发送请求,请求源自何处,或者客户端的喜好和及能力
        • 首部字段名说明
          Accept告诉服务器能够发送哪些媒体类型
          Accept-Charset告诉服务器能够发送哪些字符集
          Accept-Encoding告诉服务器能够发送哪些编码方式
          Accept-Language告诉服务器能够发送哪些语言
          Authorization包含了客户端提供给服务器,以便对其自身进行认证的数据
          From提供了客户端用户的E-mail地址
          Host给出了接收请求的服务器的主机名和端口号
          If-Match如果实体标记与文档当前的实体标记相匹配,就获取这份文档
          If-Modified-Since除非在某个指定的日期之后资源被修改过,否则就限制这个请求
          If-None-Match如果提供的实体标记与当前文档的实体标记不相符,就获取文档
          If-Range允许对文档的某个范围进行条件请求
          If-Unmodified-Since除非在某个指定日期之后资源没有被修改过,否则就限制这个请求
          Max-Forward将请求转发给其他代理或网关的最大次数
          Proxy-Authorization与Authorization首部相同,但这个首部实在与代理进行认证时使用
          Range如果服务器支持范围请求,就请求资源的指定范围
          Referer提供包含当前请求URI的文档的URL
          TE告诉服务器可以使用哪些扩展传输编码
          User-Agent将发起请求的应用程序名称告知服务器
      • 实体首部:提供有关实体及其内容得到大量信息
        • 首部字段名说明
          Allow资源可支持的HTTP方法
          Content-Encoding实体主体适用的编码方式
          Content-Language实体主体的自然语言
          Content-Length实体主体的大小(单位:字节)
          Content-Location替代对应资源的URI
          Content-MD5实体主体的报文摘要
          Content-Range实体主体的位置范围
          Content-Type实体主体的媒体类型
          Expires实体主体过期的日期时间
          Last-Modified资源的最后修改日期
    • 消息正文:实际传输的数据,可以是纯文本,也可以是图片、视频等二进制数据

  • 响应报文:由响应行,头部字段集合,消息正文三大部分组成。
    请添加图片描述

    • 响应行:描述响应的基本信息
      • HTTP版本:上面已经介绍过了
      • 状态码:状态码的职责是当客户端向服务端发送请求时,描述返回的请求结果
        • 状态码类别原因短语
          1XX信息性状态码接收的请求正在处理
          2XX成功状态码请求正常处理完毕
          3XX重定向状态码需要进行附加操作以完成请求
          4XX客户端错误状态码服务端无法处理请求
          5XX服务端错误状态码服务器处理请求出错
        • 常用的错误码主要有14种
        • 错误码错误码描述详细描述
          200OK表示从客户端发来的请求在服务端被正常处理了
          204No Content无内容。服务器成功处理,但未返回内容
          206Partial Content部分内容。服务器成功处理了部分GET请求
          301Moved Permanently永久重定向,意思是本地请求的资源以及不存在,使用新的URI再次访问
          302Found临时重定向,临时则所请求的资源暂时还在,但是目前需要用另一个URI访问
          303See Other与301类似,使用GET和POST请求查看
          304Not Modified运用于缓存控制。它用于 If-Modified-Since 等条件请求,表示资源未修改,可以理解成"重定向已到缓存的文件"
          307Temporary Redirect临时重定向,与302类似,使用GET请求重定向
          400Bad Request客户端请求的语法错误,服务器无法理解
          401Unauthorized表示发送的请求需要有通过HTTP认证的认证信息
          403Forbidden这一个是表示服务器禁止访问资源。原因比如涉及到敏感词汇、法律禁止等
          404Not Found服务器无法根据客户端的请求找到资源
          500Internal Server Error服务器内部错误,无法完成请求
          503Service Unavailable表示服务器当前很忙,暂时无法响应服务,我们上网时有时候遇到的"网络服务正忙,请稍后重试"的提示信息就是状态码 503
      • 状态码描述:作为状态码补充,是更详细的解释文字,帮助理解原因
    • 头部字段合集:上面已经介绍过,这里只介绍下响应首部字段
      • 响应首部
        • 首部字段名说明
          Accept-Ranges对此资源来说,服务器可接受的范围类型
          Age响应持续时间
          ETag资源的匹配信息
          Location令客户端重定向至指定URI
          Proxy-Authenticate代码服务器对客户端的认证信息
          Retry-After如果资源不可用,在此日期或时间重试
          Server服务器应用程序软件的名称和版本
          Vary代理服务器缓存的管理信息
          WWW-Authenticate服务器对客户端的认证信息
    • 消息正文

C++实现http服务

  • 我参考TinyHttpd项目,使用C++实现了一个http服务,功能比较简单,目前只支持GET和POST请求。并且也只是对http请求报文进行了解析,然后进行简单回应,未实现其他功能。使用第三方json解析库json11对json报文体进行解析处理。
  • 项目源代码可以从这里下载:项目地址
  • 主要代码
    •   #include "httpd.h"
        
        void threadFunc(void* arg, int conn){
        	Httpd* httpd = (Httpd*)arg;
      
        	// 接收http请求
        	char bodyBuf[1024] = {0};
        	int recvSize = recv(conn, bodyBuf, sizeof(bodyBuf), 0);
        	printf("%s\n", bodyBuf);
      
        	std::string strMethod;
        	std::string strUri;
        	std::string strVersion;
        	std::map<std::string, std::string> requestHead;
        	std::string requestBody;
        	// 解析http请求,包括请求方式(目前只支持GET和POST请求),URI,http版本
        	httpd->parseHttpRequestInfo(bodyBuf, strMethod, strUri, strVersion);
        	// 解析http请求头
        	httpd->parseHttpRequestHead(bodyBuf, requestHead);
        	//解析http请求体
        	httpd->parseHttpRequestBody(bodyBuf, requestBody);
      
        	//根据不同请求方式进行响应
        	if(strMethod.compare("GET") == 0){
        		httpd->httpResponseHtml(conn);
        	 }else if(strMethod.compare("POST") == 0){
        		std::string data1;
        		std::string data2;
        		if(httpd->parseBodyJson(requestBody, data1, data2)){
            		httpd->httpResponseJson(conn, data1, data2);
        		}
        	}
        	//关闭套接字
        	close(conn);
        }
      
        bool Httpd::start(){
        	//定义sockfd
        	int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);
      
        	///定义sockaddr_in
        	struct sockaddr_in server_sockaddr;
        	server_sockaddr.sin_family = AF_INET;
        	server_sockaddr.sin_port = htons(4000);
        	server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
      
        	//bind,成功返回0,出错返回-1
        	if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1){
        		perror("bind");
        		return false;
        	}
      
        	//listen,成功返回0,出错返回-1
        	if(listen(server_sockfd, 5) == -1){
        		perror("listen");
        		return false;
        	}
      
        	//客户端套接字
        	char buffer[1024] = {0};
        	struct sockaddr_in client_addr;
        	socklen_t length = sizeof(client_addr);
        	int conn = 0;
        	while(1){
        		//成功返回非负描述字,出错返回-1
        		conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);
        		if(conn < 0){
            		perror("connect");
            		return false;
        		}
      
        		//开启线程处理请求
        		std::thread th;
        		th = std::thread(threadFunc, this, conn);
        		th.join();
        	}
        	close(server_sockfd);
      
        	return true;
        }
      
        bool Httpd::parseHttpRequestInfo(std::string httpRequest, std::string& method, std::string& uri, std::string& version){
        	int recvSize = httpRequest.size();
      
        	//查找请求头
        	std::string strRequestHead;
            int pos = httpRequest.find("\r\n");
        	strRequestHead = httpRequest.substr(0, pos);
      
        	//解析请求类型
        	method = strRequestHead.substr(0, strRequestHead.find(" "));
        	//解析uri
        	uri = strRequestHead.substr(strRequestHead.find(" ") + 1, strRequestHead.find(" ", strRequestHead.find(" ") + 1) - strRequestHead.find(" "));
        	//解析http版本
        	version = strRequestHead.substr(strRequestHead.rfind(" "), strRequestHead.size() - strRequestHead.rfind(" "));
        	return true;
        }
      
      
        bool Httpd::parseHttpRequestHead(std::string httpRequest, std::map<std::string, std::string>& requestHead){
        	int recvSize = httpRequest.size();
        	int headPos = httpRequest.find("\r\n");
      
        	int bodySize = parseBodySize(httpRequest);
      
        	std::string strRequestH;
        	do{
        		int iPos = httpRequest.find("\r\n", headPos + strlen("\r\n"));
        		strRequestH = httpRequest.substr(headPos, iPos - headPos);
        		if(strRequestH.find(":") != std::string::npos){
            		std::string strKey = strRequestH.substr(0, strRequestH.find(":"));
            		std::string strValue = strRequestH.substr(strRequestH.find(":") + 1, strRequestH.size() - strRequestH.find(":"));
            		requestHead.insert(std::pair<std::string, std::string>(strKey, strValue));
        		}
        		headPos = iPos;
        	} while(headPos < recvSize - bodySize && headPos > 0);
      
        	return true;
        }
      
        bool Httpd::parseHttpRequestBody(std::string httpRequest, std::string& requestBody){
        	int recvSize = httpRequest.size();
      
        	int bodySize = parseBodySize(httpRequest);
        	if(bodySize == 0){
        		return false;
        	}
      
        	requestBody = httpRequest.substr(recvSize - bodySize, bodySize);
        	return true;
        }
      
        int Httpd::parseBodySize(std::string httpRequest){
        	std::string strContentLength;
        	int posLengthStart = httpRequest.find("Content-Length: ") + strlen("Content-Length: ");
        	int posLengthEnd = httpRequest.find("\r\n", httpRequest.find("Content-Length: ") + strlen("Content-Length: "));
        	strContentLength =  httpRequest.substr(posLengthStart, posLengthEnd - posLengthStart);
        	return atoi(strContentLength.c_str());
        }
      
  • 通过代码我们可以看到,其实底层还是TCP编程,只不过TCP通信时,我们是直接拿数据,不用遵守什么规则。但如果要进行HTTP通信,就要遵守人家的规则,按照请求报文的格式去进行解析,才能拿到服务端想要的信息,然后再根据响应报文去组装数据,返回给客户端。

演示

  • POST请求演示,我通过postman演示下post请求,目前实现的功能是将请求数据拼接后返回。
    • postman界面演示
      在这里插入图片描述
    • 服务端打印
      请添加图片描述
  • GET请求演示,直接在浏览器中访问,返回一个html格式的页面
    • 浏览器页面
      在这里插入图片描述
    • 服务端打印
      在这里插入图片描述

抓包分析

  • 下面我们通过wireShark工具抓包分析下http协议的通信过程,发送一个post请求。
    在这里插入图片描述
  • 通过抓包可以看到,在http通信前,先要通过TCP三次握手建立连接,并且一次请求结束后,进行TCP四次挥手断开连接(http协议目前是支持长连接的,也就是建立连接后,可以发送多个http请求,我这里为了分析方便,在发送一次http请求后就关闭了套接字)。
  • 先看下前三行,是TCP建立连接的过程,我在使用wireShark抓包分析TCP协议进行了详细介绍,这里就不再过多阐述了。
  • 第四行开始是http通信,可以看到http请求的所有信息
    在这里插入图片描述
  • 再看第七行,是http服务的响应
    在这里插入图片描述
  • 后面是TCP四次挥手过程,这里也不过多阐述了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HTTP协议详解 - 通过C++实现HTTP服务剖析HTTP协议 的相关文章

  • 【linux】程序找不到动态库.so的解决办法|查看.so动态库信息|.so动态库加载顺序

    目录 找不到 so解决方法 方法一 xff1a 添加环境变量 方法二 xff1a 复制so文件到lib路径 方法三 xff1a xff08 推荐 xff09 添加ldconfig寻找路径 方法四 xff1a 在编译目标代码时指定该程序的动态
  • 使用Arduino开发ESP32(08):TCP Client与TCP Server使用

    文章目录 目的TCP Client使用说明常用方法基础使用演示作为WEB Client使用 TCP Server使用说明常用方法基础使用演示作为WEB Server使用 总结 目的 TCP是网络应用中常用的功能 xff0c 很多高级功能也是
  • ModBus学习笔记

    一 什么是ModBus xff1f 1 预备知识 xff08 1 xff09 什么是通讯协议 xff1f 通信协议是指双方实体完成通信或服务所必须遵循的规则和约定 通过通信信道和设备互连起来的多个不同地理位置的数据通信系统 xff0c 要使
  • Jetson TX2 将系统迁移到SD卡,系统文件修改方式

    系统迁移步骤 xff1a 格式化SD卡 复制系统到SD卡 修改系统文件 1 在原系统盘内 cd boot extlinux sudo vim extlinux conf 该文件初始内容如下 xff1a TIMEOUT 30 DEFAULT
  • svn中打标签的一种方法

    SVN创建标签的方法 方法一 xff1a TortoiseSVN客户端浏览创建 选中需要创建标签的目录 xff0c 右键 gt copy to 在弹出框中输入新建标签所在的URL地址 xff0c 填写log信息 xff0c 确定 方法二 x
  • (图解 HTTP)一篇文章带你深入了解 HTTP 协议

    文章目录 一 了解客户端和服务器通讯的过程二 HTTP 是不保存状态的协议三 请求 URI 定位资源四 告知服务器意图的 HTTP 方法1 GET xff1a 获取资源2 POST xff1a 传输实体主体3 PUT xff1a 传输文件4
  • VC编译选项

    C 在预处理输出中保留注释语句 c 只编译 xff0c 不连接 xff0c 相当于在 34 Build 34 菜单下选择了 34 Compile 34 D 定义常量和宏 xff0c 与源程序里的 define 有相同效果 E 预处理C C
  • C语言中String库函数

    为了以后学习以及查阅方便 xff0c 转贴在此 xff0c 若有雷同 xff0c 敬请包含 文中内容摘自 C程序设计教程 xff08 美 xff09 H M Deitel P J Deitel著 xff0c 薛万鹏等译 xff0c 机械工业
  • JAVA与海康威视人脸机对接,使用ISUP方式

    1下载DEMO包 下载地址 JAVA海康威视人脸机isup方式对接demo包 Java文档类资源 CSDN下载 2设置依赖 需要把examples jar和jna jar引入项目 3配置本地 config properties 把ip地址设
  • Keil工程

    文章目录 1 Keil工程添加源文件和头文件 xff08 c和 h xff09 的方法1 方式一2 方式二 2 keil工程生成的MAP文件取消优化 1 Keil工程添加源文件和头文件 xff08 c和 h xff09 的方法 1 方式一
  • 2020-09-28

    通用异步收发器 xff08 Universal Asynchronous Receiver Transmitter xff0c 通常称作UART xff0c 是一种串行 异步 全双工的通信协议 xff0c 在嵌入式领域应用的非常广泛 UAR
  • 【cmake】CMakeList添加库|添加头文件|添加路径|add_executable、add_library、target_link_libraries|添加编译选项|宏开关

    目录 官网查阅 开胃菜例子 CMakeLists生成和添加依赖库 CMakeLists更多小例子 生成 so共享库文件 调用 so共享库文件 生成一个可执行程序的 CMakeList 生成一个 so动态库的 CMakeList add li
  • TCP连接的建立

    前言 xff1a TCP的问题已然困惑我很久了 xff0c 一直是一知半解 xff0c 靠记忆来记住TCP连接的过程 xff0c 不能根本上理解 xff0c 漏洞百出 xff0c 最近抽时间把TCP经典书籍 TCP IP详解 阅读了一下 废
  • 【Nokov】动作捕捉系统培训笔记

    Nokov度量科技 简介 xff1a Nokov是一种光学三维动作捕捉系统 xff0c 采用红外镜头捕捉被动发光标记点 xff0c 构建三维数据的动作采集与分析系统 xff0c 运用于运动分析 步态康复 模拟训练 机械仿生 机器人 无人机
  • 【Nokov】动作捕捉系统标定与机械臂各坐标系的说明

    导语 xff1a 这一周的工作先是完成了度量系统Nokov的标定 xff0c 然后对机械臂自身的编码器得到的坐标值与动作捕捉系统Nokov测得的坐标值进行了比较 xff0c 来观察二者之间的误差 在这个过程中我对Nokov软件Seeker的
  • 【Nokov】关于动捕系统获取刚体姿态的说明

    动作捕捉系统Nokov获取刚体的姿态信息 前言 xff1a 对于动捕系统软件Seeker的基本使用以及获取单个Marker的位置操作已经比较熟悉了 xff0c 对于机械臂而言 xff0c 接下来就是获取它的姿态信息 xff0c 经过昨天下午
  • 【机器人】机械臂与动捕Nokov的深入了解

    导语 xff1a 每次的实践操作后 xff0c 总能刷新我对机械臂以及Nokov的认识 xff0c 既让我惊喜不已 xff0c 同时也让我知道我掌握的还远远不够 xff0c 需要不断的学习 关于机械臂 示教器上NOA姿态表示方式 xff1a
  • Ubuntu18.04+ROS+kalibr标定工具箱安装编译

    目录 前言 一 安装ROS 1 设置镜像源 2 更新软件包索引 3 安装ROS 4 测试ROS是否安装成功 二 安装kalibr melodic 1 kalibr简介 2 安装kalibr 3 测试kalibr 参考文献 xff1a 前言
  • okhttp源码分析,Builder.ParseResult.parse(null, url) HttpUrl.parse(url) 方法详细分析

    在使用okhttp3时 以下方式具体对url进行了怎样的处理 查了许多资料没有发现有关介绍查询源码进行分析添加相关方法介绍 Request request 61 new Request Builder url 34 https www be
  • MP地面站二次开发教程(二)MP的框架与修改

    目录 MP高级功能 主界面基本修改 1 菜单名称背景修改 2 主窗体语言修改 3 主要窗体目录位置 4 菜单栏删除 5 入口函数 6 参数配置函数 定制修改步骤 1 主题环境修改 2 菜单精简 去掉冗余菜单按键 3 功能按键添加 新建按钮实

随机推荐

  • QGC地面站二次开发(三)Qt 简洁地面站

    目录 多机控制原理 多机控制实现 简洁地面站优化 1 飞机的飞行轨迹以不同的颜色区分 2 控制所有的飞机 3 将设定航线送给特定的飞机 多机控制原理 多机地面站支持 TCP UDP 和串口等三种连接方式 xff0c 首先我们需要对这两种连接
  • 基于51单片机的密码锁设计

    研究内容 本系统由STC89C52单片机系统 xff08 主要是STC89C52单片机最小系统 xff09 4 4矩阵键盘 LCD1602显示和报警系统等组成 xff0c 具有设置 修改六位用户密码 超次报警 超次锁定 密码错误报警等功能
  • 【gcc】gcc优化等级 -O1 -O2 -O3 -Os -Ofast -Og|gcc关闭优化

    目录 优化等级 O1 O2 O3 Os Ofast Og cmake 生成 debug和 release 版 Cmake设置优化等级 Debug和Release 方案 About table About question gcc g 43
  • 嵌入式期末复习题(二)

    考试题型 一 选择题 每小题2分 xff0c 15题 xff0c 共30分 二 填空题 每题2分 xff0c 10题 xff0c 共20分 三 简答题 每题5分 xff0c 4题 xff0c 共20分 四 分析题 每题5分 xff0c 3题
  • 嵌入式期末复习题(三)

    1嵌入式系统的定义 嵌入式系统是用于控制 监视或辅助操作机器和设备的装置 嵌入式系统是以应用为中心 xff0c 以计算机技术为基础 xff0c 软硬件可裁剪 xff0c 适应应用系统对功能 可靠性 成本 体积和功耗等严格要求的专用计算机系统
  • 解决Ubuntu 网速慢的问题

    Ubuntu 网速慢 xff0c 主要是把时间浪费在域名解析上 我们可以用dnsmasq解决这问题 具体如下 xff1a 1 安装dnsmasq 命令 sudo apt get install dnsmasq 2 编辑dnsmasq的配置文
  • C++中的char,char*,char[]

    char C 43 43 中的char是字符的意思 xff0c 可以用例如 39 a 39 来表示 xff0c 每个字符串string都是由很多个单独的字符char组成 char char 是一个指针 xff0c 例如 xff1a char
  • VSCode 运行C++程序

    0 省流自强版 本方法来自以下两个参考链接 xff0c 可自行参照去执行安装 xff1a 1 https code visualstudio com docs languages cpp 2 https www youtube com wa
  • 了解CV和RoboMaster视觉组(四)视觉组使用的硬件

    NeoZng neozng1 64 hnu edu cn 4 视觉组接触的硬件 虽然别人总觉得视觉组就是整天对着屏幕臭敲代码的程序员 xff0c 实际上我们也会接触很多的底层硬件与传感器 xff0c 在使用硬件的同时很可能还需要综合运用其他
  • VINS-RGBD运行指令

    创建工程VINS RGBD catkin ws 将代码放入src文件夹当中 git clone https github com STAR Center VINS RGBD 进行编译 cd VINS RGBD catkin ws catki
  • ubuntu16.04安装realsense D435i驱动及固件

    安装Realsense SDK xff1a 1 下载source并且确定git版本 xff1a 1 git clone https github com IntelRealSense librealsense xff08 下载源 xff09
  • ROS入门(七)——仿真机器人三(Gazebo+Xacro)

    所用的学习链接 xff1a 奥特学园 ROS机器人入门课程 ROS理论与实践 零基础教程P271 277 以上视频笔记见http www autolabor com cn book ROSTutorials 前文参考 ROS入门 五 仿真机
  • ROS入门(九)——机器人自动导航(介绍、地图、定位和路径规划)

    所用的学习链接 xff1a 奥特学园 ROS机器人入门课程 ROS理论与实践 零基础教程P289 314 以上视频笔记见http www autolabor com cn book ROSTutorials 一 介绍 官方链接 xff1a
  • Keil工程添加源文件和头文件(.c和.h)的方法

    在此把Keil项目添加源文件和头文件的方法做个记录 xff1a 1 Keil项目添加源文件和头文件的方法之一 1 1 右键点击项目名称 xff0c 弹出菜单中选择Add Group xff0c 我们把所有需要添加的源文件都放在这个Group
  • 漂亮的html表格

    原文 xff1a http www textfixer com resources css tables php css table01 一个像素边框的表格 xff1a Info Header 1 Info Header 2 Info He
  • SIPp之认证注册

    欢迎大家转载 xff0c 为保留作者成果 xff0c 转载请注明出处 xff0c http blog csdn net netluoriver xff0c 有些文件在资源中也可以下载 xff01 如果你没有积分 xff0c 可以联系我 xf
  • HTTP:DIGEST认证的请求和响应报文

    以下是HTTP DIGEST认证的请求和响应报文的例子 xff0c 供以后参考 IE first request GET boe checkedServlet HTTP 1 1 Accept image gif image jpeg ima
  • Linux配置篇 | Ubuntu配置apt镜像源

    以下以 Ubuntu18 04 LTS 为例 xff0c 也适用于 Ubuntu 其他版本 一 修改apt镜像源 xff08 1 xff09 备份apt配置文件 xff1a cp etc apt sources list etc apt s
  • STC89C52RC单片机额外篇 | 04 - 认识头文件<intrins.h>与_nop_函数

    1 lt intrins h gt 头文件 头文件 lt intrins h gt 在我们51单片机日常开发中经常使用 xff0c 特别是 nop 函数 xff0c 以下是 lt intrins h gt 的内容 xff1a span cl
  • HTTP协议详解 - 通过C++实现HTTP服务剖析HTTP协议

    前言 C C 43 43 程序员一般很少会接触到HTTP服务端的东西 xff0c 所以对HTTP的理解一般停留在理论 本文章实现通过C 43 43 实现了一个http服务 xff0c 可以通过代码对HTTP协议有更深的理解 xff0c 并且