什么TCP几层模型,什么几次握手就不扯了。让我们从代码层面来解析下http协议,主要就是用socket实现一个客户端的http,通过手动构造socket传输连接数据可以很清晰的明白http的协议内容。

  1. GET

    1. 请求协议

简单来说就是所有数据都是一行一行的文本(所以才叫文本协议吧),用\r\n换行,最后结束的时候多一个空行。

假设我们要发送get请:http://127.0.0.1:1234/ad1/ad2/?name=a&age=1

然后其中的headers中包含两个键值对:ABC:123、DEF:456

对应的数据就是这样:

页面路径中?开始为参数,通过&分割参数,每个参数用key=val形式。一般框架都可以自动解析路径中的参数。

  1. 响应协议

和请求协议是一样。需要注意的就是这里的headers内的Content-Length,是比较重要的一个返回参数,用来标记返回消息的数据长度。同理Content-Type也就很重要,一般用来标记返回的数据是什么类型,比如application/json、image/jpeg等等,http是文本传输协议,主要指的是协议头,而内容就可以是二进制流,不需要做成字符串。

假设服务器返回了“funCallback”这个字符串,字符串长度11

对应的主要数据就是这样:

  1. 测试代码

    1. http服务

用python写个简单的服务。

from urllib.parse import urlsplit, parse_qs  from http.server import HTTPServer, BaseHTTPRequestHandler  class ProHeader(BaseHTTPRequestHandler):  def do_GET(self):print("pageaddr: " + self.path)try:print("ABC: " + self.headers['ABC'])  #获取headers中的ABC参数   123print("DEF: " + self.headers['DEF'])  #获取headers中的ABC参数   456except Exception as e:print(e)rsp = "funCallback"  rsp = rsp.encode("utf8")self.send_response(200)self.send_header("Content-Length", str(len(rsp)))self.end_headers()self.wfile.write(rsp)  if __name__ == '__main__':  httpd = HTTPServer(('', 1234), ProHeader)  httpd.serve_forever()
  1. 客户端请求

这里直接用C#的socket,按照协议组合数据,然后进行发送和接收。

Socket sokClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);sokClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));StringBuilder sb = new StringBuilder();sb.Append("GET /ad1/ad2/?name=a&age=1  HTTP/1.1\r\n");//第一行//n个headerssb.Append("ABC:123\r\n");sb.Append("DEF:456\r\n");sb.Append("\r\n");//末尾空行//发送请求数据string datstr = sb.ToString();byte[] bs = Encoding.UTF8.GetBytes(datstr);sokClient.Send(bs, bs.Length, 0);//接收请求返回数据byte[] by = new byte[1];MemoryStream msHead = new MemoryStream();int ContentLength = 0;while (true){int ret = sokClient.Receive(by);if (ret <= 0) break;msHead.Write(by, 0, 1);string revdata = Encoding.UTF8.GetString(msHead.ToArray());if (revdata.Contains("\r\n\r\n")){//判断为末尾空行,获取返回的数据长度ContentLength = Convert.ToInt32(Regex.Match(revdata, "(?<=(Content-Length:)).*(?=\r)").Value.ToString());break;}}//根据ContentLength长度接收数据内容byte[] revDataBy = new byte[ContentLength];int revLen = 0;while (revLen < ContentLength){int read = sokClient.Receive(revDataBy, revLen, ContentLength - revLen, SocketFlags.None);revLen += read;}Console.Write("====head====\n");Console.WriteLine(Encoding.UTF8.GetString(msHead.ToArray()));Console.Write("\n====rev data====\n");Console.WriteLine(Encoding.UTF8.GetString(revDataBy));
  1. 运行结果

服务器接收数据并解析数据头,结果如下:

客户端发送后,解析服务端的结果如下:

  1. POST

post和get协议一样,区别就在于post发送时,第一行的请求方法由GET变成了POST。

然后最重要的就是post可以发送大一些的数据,不像get只能在headers和地址中写字符串。

发送时headers内加上Content-Length和Content-Type这种,然后传输完协议头继续就可以传输数据内容了。

我们就简单写一个通过Post发送图像的例子测试一下。

  1. http服务

服务器接收POST请求,然后通过Content-Length直接读发送的数据大小,然后存储成a.jpg就行。

from urllib.parse import urlsplit, parse_qs  from http.server import HTTPServer, BaseHTTPRequestHandler  class ProHeader(BaseHTTPRequestHandler):  def do_POST(self):jpgdat = self.rfile.read(int(self.headers['Content-Length']))pf = open("a.jpg","wb")pf.write(jpgdat)pf.close()    if __name__ == '__main__':  httpd = HTTPServer(('', 1234), ProHeader)  httpd.serve_forever()
  1. 客户端请求

客户端读取图像,将长度写入headers内的Content-Length,然后发送数据头和内容即可。

FileInfo fi = new FileInfo("D:\\1.jpg");byte[] jpgbuf = new byte[fi.Length];fi.OpenRead().Read(jpgbuf, 0, jpgbuf.Length);StringBuilder sb = new StringBuilder();sb.Append("POST /ad1  HTTP/1.1\r\n");//第一行sb.Append("Content-Length:" + jpgbuf.Length.ToString() + "\r\n");  //headers 设置标志数据长度sb.Append("\r\n");//末尾空行//发送请求数据string datstr = sb.ToString();byte[] bs = Encoding.UTF8.GetBytes(datstr);Socket sokClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);sokClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));//将数据头和数据内容发送sokClient.Send(bs, bs.Length, 0);sokClient.Send(jpgbuf, jpgbuf.Length, 0);Console.ReadLine();

Http协议简易分析相关推荐

  1. Linux内核网络数据包发送(三)——IP协议层分析

    Linux内核网络数据包发送(三)--IP协议层分析 1. 前言 2. `ip_send_skb` 3. `ip_local_out` and `__ip_local_out` 3.1 netfilt ...

  2. Linux内核网络数据包发送(二)——UDP协议层分析

    Linux内核网络数据包发送(二)--UDP协议层分析 1. 前言 2. `udp_sendmsg` 2.1 UDP corking 2.2 获取目的 IP 地址和端口 2.3 Socket 发送:b ...

  3. HTTPS协议原理分析

    HTTPS协议原理分析 HTTPS协议需要解决的问题 HTTPS作为安全协议而诞生,那么就不得不面对以下两大安全问题: 身份验证 确保通信双方身份的真实性.直白一些,A希望与B通信,A如何确认B的身份 ...

  4. UDT协议实现分析——连接的建立

    UDT Server在执行UDT::listen()之后,就可以接受其它节点的连接请求了.这里我们研究一下UDT连接建立的过程. 连接的发起 来看连接的发起方.如前面我们看到的那样,UDT Clien ...

  5. UDT协议实现分析——UDT Socket的创建

    UDT API的用法 在分析 连接的建立过程 之前,先来看一下UDT API的用法.在UDT网络中,通常要有一个UDT Server监听在某台机器的某个UDP端口上,等待客户端的连接:有一个或多个客户 ...

  6. 针对CDP协议攻击分析及安全防护

    针对CDP协议攻击分析及安全防护<?xml:namespace prefix="o"> ?xml:namespace> 熟悉Cisco的朋友都知道CDP协议是思科 ...

  7. FTP协议的分析和扩展

    2019独角兽企业重金招聘Python工程师标准>>> FTP协议的分析和扩展 出处: http://elly.blogdriver.com/index.jsp >> 1 ...

  8. 一起来用Websocket(二):Websocket协议详细分析

    一起来用Websocket(二):Websocket协议详细分析 前言 本节主要翻译一下websocket的协议.其中,socket通信开发,最重要的就是协议了.通信软件(QQ.MSN).杀毒软件(3 ...

  9. 关于RDP协议的分析 附上RDP 协议初步分析.pdf文件

    关于RDP协议的分析和研究                                         -------------- leadgenius 写这个一是便于学习,再就是与网友们共同讨 ...

  10. SAP中采购合同与采购计划协议关联性分析(续)

    在阅读本文之前,建议先参考笔者的上一篇博文<SAP中采购合同与采购计划协议关联性分析>.在采购合同与采购计划协议关联应用的企业中,遇到一些问题.笔者认为可以展开分析一下. 当采购计划协议参 ...

最新文章

  1. oracle数据库配置失败,oracle11g – Oracle 11G XE安装错误:数据库配置失败
  2. PCA主成分分析/协方差矩阵
  3. xcode编译项目Permission denied错误
  4. 考研【文法方向专场讲座】附:通信工程院校排名
  5. python批量新建文件_python批量处理
  6. Qt工作笔记-QStylePlugin插件实现变化窗体背景
  7. System.arraycopy()实现数组之间的复制
  8. linux 网络端口全连接扫描,端口全连接扫描程序(Linux, socket):TCP的connect方式...
  9. JavaScript权威指南 - 数组
  10. 博图能打开s7200吗_透明胶真的能把车窗打开吗?现场实验给你看,能成功吗?...
  11. Atitit.uml2 api 的编程代码实现设计uml开发 使用eclipse jar java 版本
  12. 高级GIS-1.提取纯净像元
  13. 人脸识别算法-LBP算法及python实现
  14. sketch插件的学习 末尾链接有彩蛋
  15. html5 旋转木马相册,HTML5 CSS3 专题 :诱人的实例 3D旋转木马效果相册
  16. 卸载计算机系统,W7电脑系统如何卸载软件
  17. 全球及中国建筑设计行业十四五发展方向与投资决策建议报告2022版
  18. css实现渐变色边框动态旋转
  19. python编写一个函数判断一个数是否为素数是则返回yes_编写函数,判断一个整数是否为素数,并编写主程序调用该函数。_学小易找答案...
  20. vue3之axios配置(阿飞)

热门文章

  1. spring data 接口之 JpaRepository,JpaSpecificationExecutor
  2. Ansible基本配置以及使用示例
  3. 构造一个简单的linux系统
  4. 解决“/bin/bash^M: bad interpreter: No such file or directory”
  5. 互联网+正在颠覆行车记录仪市场
  6. DDD~microsoft NLayerApp项目中的层次结构图
  7. Node rabbitmq 入门就够了
  8. python爬虫设置代理ip_python爬虫使用代理ip或请求头的问题
  9. python3安装scapy_centos 7 安装python3.7 和scapy
  10. 10年老电脑如何提速_电脑上如何提取图片中的文字?教你3个方法,10秒轻松搞定...