HTTP请求方式和报文解析
一、概述
最近想尝试写一个关于网络请求的系列文章,将网络请求的基础、使用及网络框架的学习分析总结以下,大致准备从以下几个方面分析:
- 网络请求的基础
- HTTP请求方式和报文解析
- Cookie 和 Session的理解与使用
- HTTP Cache缓存机制
- 封装网络请求
- TCP 和 Socket
二、HTTP请求方式
HTTP提供了七种请求方式:GET、POST、DELETE、PUT、HEAD、TRACE、OPTIONS,其中PUT,DELETE、POST、GET分别对应了资源的增、删、改、查,也是使用最多的请求方式;
- GET
- GET请求报文 和 服务器的响应报文
上述请求的资源是www.devtf.cn/articles/123.html文件,GET请求是将请求参数放在URL之后,第一个参数之前使用“?“,之后的参数格式为:参数名=参数值,参数名之间使用”&“连接,如:www.devtf.cn/articles/123.html?username=myname&userid=123
- POST
POST请求通常是使用来提交HTML的表单,表单中的数据传输到服务器,由服务器对这些数据处理,请求和响应的报文如下:
- PUT
与GET从服务器获取数据相反的是,PUT是想服务器写入资源,比如像CSDN这样允许用户创建Web页面,并用PUT直接传输到服务器上,返回服务器上的资源地址;
- DELETE
使用方法和GET一样,请求删除URL指定的资源文件
三、HTTP请求报文
HTTP的请求报文由请求行(Request line)、请求头部(Header)空行和请求数据;
- 请求行:请求报文的第一行,用来说明以什么方式请求、请求的地址和HTTP版本
- 头部字段:每个头部字段都包含一个名字和值,二者之间采用“:”连接,如:Connection:Keep-Alive
- 请求数据:请求的主体根据不同的请求方式请求主体不同
- GET、DELETE
这两种请求报文比较简单,查看上面即可
- POST、PUT
POST和PUT的请求行和请求头部,在上述已经列出,现在主要介绍请求报文中的参数:
- 一个参数的开始是由“--”加上boundary开始的
- 然后加上参数的Header信息,格式为字段名和字段值,二者之间使用“:”连接,如:Content-Type:text/plain
- 加上一个空行
- 发送的参数值
- 请求的数据以“--”+boundary+“--”结束真个请求的报文结束符
四、HTTP响应报文
HTTP的响应报文为3个部分组成:状态行、消息报文、响应正文
- 状态行:由HTTP版本、响应状态码、响应状态描述;如:HTTP/1.1 200 OK
- 响应报文头部:使用关键字和值表示,二者使用“:”隔开;如:Content-Type:text/html
- 响应内容:请求空行之后就是请求内容
- 常见的状态码和描述
- 200 OK : 客户端请求成功
- 400 Bad Request:客户端请求语法错误,服务器无法解析
- 401 Unauthorized:请求未经授权
- 403 Forbidden:服务器收到请求拒绝服务
- 404 Not Found:请求资源不存在,常见URL错误
- 500 Internal Server Error:服务端不可预期错误
- 503 Server Unavailable:服务器当前不能处理客户端请求
五、简单模拟HTTP服务器
- 创建HttpServer:内部创建ServerSocket监听客户端的输出信息
public const val HTTP_PORT = 8080 // 监听的端口
class HttpServiceSocket : Thread() {val mServiceSocket by lazy {ServerSocket(HTTP_PORT) // 创建ServerSocket}override fun run() {while (true){Log.d("HttpServiceSocket","Service 等待输入...")DeliverThread(mServiceSocket.accept()).start() //开启线程接收信息}}
- 为了不阻塞线程,再开辟新线程从输入流中读取数据
class DeliverThread(val socket: Socket) : Thread() {val bufferedReader by lazy {BufferedReader(InputStreamReader(socket.getInputStream()))}val printStream by lazy {PrintStream(socket.getOutputStream())}val headerParamsMap = mutableMapOf<String,String>() // 储存Header的参数信息val paramsMap = mutableMapOf<String,String>() // 储存参数的参数信息lateinit var httpMethod : Stringlateinit var subPath : Stringlateinit var boundary : Stringvar isParseHeader = falseoverride fun run() {super.run()parseRequest() // 解析RequesthandlerResult() // 构建返回的ResponsebufferedReader.close()printStream.close()socket.close()}
}
- 解析Request:parseRequest()
private fun parseRequest() {var line = 1var lineString : String? = bufferedReader.readLine()while (lineString != null){if (line == 1){parseRequestLine(lineString)// 解析请求行}if (line != 1 && !isParseHeader){parserHeader(lineString) // 解析请求头部}if (isParseHeader){parseParams(lineString) // 解析参数}lineString = bufferedReader.readLine() //循环读取数据line++}}
- 解析请求行、请求头部、请求参数
// 解析请求行private fun parseRequestLine(lineString: String) {val strings = lineString.split(" ")Log.d("Http Method",strings[0])Log.d("Http Path",strings[1])Log.d("Http Version",strings[2])}// 解析请求头部private fun parserHeader(lineString: String) {if (lineString == ""){isParseHeader = trueLog.d("Http Request","-------Header 解析完成 -------")return}else if (lineString.contains("boundary")){boundary = parseBoundary(lineString)Log.d("Http Request","boundary=$boundary")}else{val strings = lineString.split(":")headerParamsMap[strings[0]] = strings[1]Log.d("Http Content","${strings[0] .trim()} : ${strings[1] .trim()}")}}private fun parseBoundary(lineString: String): String {val strings = lineString.split(";")parserHeader(strings[0])if (strings[1] != null){return strings[1].split("=")[1]}return ""}private fun parseParams(lineString: String) {if (lineString == "--$boundary"){Log.d("Http Content",lineString)parseParamsType()}}private fun parseParamsType() {val stringParams = bufferedReader.readLine()Log.d("Http Content",stringParams)val name = parseBoundary(stringParams)bufferedReader.readLine()val value = bufferedReader.readLine()paramsMap[name] = valueLog.d("Http Content"," ")Log.d("Http Content","$value")}
- 模拟POST请求
class HttpPost(var url:String) {private lateinit var mSocket: Socket // 创建Socketval paramsMap = mutableMapOf<String,String>() // 储存设置的信息fun add(name : String, value : String){ // 添加参数paramsMap[name] = value}fun execute(){mSocket = Socket(url, HTTP_PORT)val printStream = PrintStream(mSocket.getOutputStream())val bufferedReader = BufferedReader(InputStreamReader(mSocket.getInputStream()))val boundary = "http_boundary_123"writeHead(boundary,printStream)writeParams(boundary,printStream)writeResponse(bufferedReader)}// 输出返回的Responseprivate fun writeResponse(bufferedReader: BufferedReader) {Log.d("Http Response","请求结果...")Thread{var string = bufferedReader.readLine()while (string == null || !string.contains("HTTP")){string = bufferedReader.readLine()}while (string != null){Log.d("Http Response",string)string = bufferedReader.readLine()}}.start()}// 写入参数private fun writeParams(boundary: String, printStream: PrintStream) {var iterator = paramsMap.keys.iterator()while (iterator.hasNext()){val name = iterator.next()printStream.println("--$boundary")printStream.println("Content-Disposition: from-data; name=$name")printStream.println()printStream.println(paramsMap.get(name))}printStream.println("--$boundary--")}
//写入请求头部private fun writeHead(boundary: String, printStream: PrintStream) {printStream.println("POST /api/login/ HTTP/1.1")printStream.println("content-length:123")printStream.println("Host:$url:$HTTP_PORT")printStream.println("Content-Type:multipart/from-data;boundary=$boundary")printStream.println("User-Agent:android")printStream.println()}
}
- 启动ServerSocket并发送请求信息
btnService.setOnClickListener { HttpServiceSocket().start() }btnPost.setOnClickListener {Thread {val httpPost = HttpPost("127.0.0.1")httpPost.add("userName","Simple")httpPost.add("pwd","pwd_123")httpPost.execute()}.start()}
- 运行后输出信息
HTTP请求方式和报文解析相关推荐
- get 和 post 请求方式 及其参数解析
一.Get与Post区别 Get和Post都是Http协议的组件,所以底层都是使用tcp链接.Get的请求方式是将http的header和data一并发往服务端,也就是一条tcp数据包发送,这就会 ...
- WebService soap报文请求与响应报文解析
需求 今日公司要做一个协同办公系统(OA),PC端已经完成.现在要做一个手机端网页端的.从登陆入手,需要向 服务端发送一段请求报文获取响应报文,对响应报文进行解析判断是否登录成功. 当然手机客户端发送 ...
- js跨域请求方式 ---- JSONP原理解析
这篇文章主要介绍了js跨域请求的5中解决方式的相关资料,需要的朋友可以参考下 跨域请求数据解决方案主要有如下解决方法: 1 2 3 4 5 JSONP方式 表单POST方式 服务器代理 Html5的X ...
- 航信电子发票开发(servlet请求方式)
在系统用户交费后,需要打印发票,可以选择普票或者机打票(票据信息在系统中自定义设置的),也可以打印电子发票,这里对接的是航信的电子发票,请求方式非web服务,而是使用servlet通过HTTP请求的方 ...
- 支付系统设计三:渠道网关设计02-客户端报文解析
文章目录 前言 一.后台配置管理 1.1 渠道配置 1.1.1 渠道基本信息新增 1.1.2 渠道交易类型配置 1.1.3 渠道商户信息配置 1.1.4 账户配置 1.1.5 交易类型机构配置 1.2 ...
- http协议与https协议+UDP协议和TCP协议+WebSocket协议下服务端主动去发送信息+对称加密与非对称加密+get和post请求方式区别详解+浏览器内核以及jsj解析引擎
TCP和UDP协议是TCP/IP协议的核心. 在TCP/IP网络体系结构中,TCP(传输控制协议,Transport Control Protocol).UDP(用户数据报协议,User Data P ...
- html解析 英文,http请求报文解析(国外英文资料).doc
http请求报文解析(国外英文资料) http请求报文解析(国外英文资料) HTTP request message sample: POST/pass/demo/requesttest.jsp HT ...
- axios post json_助你解析Axios原理之一:如何实现多种请求方式
自从Axios成功打入Vue全家桶之后,便开始火的一塌糊涂!截止到目前,其在github上的star即将突破80k!可以说Axios是当下前端界最流行的ajax请求库,可(jue)能(dui)没有之一 ...
- HTTP的8种请求方式及常用请求方式的解析
一.什么是HTTP? HTTP,即超文本传输协议,是一种实现客户端和服务器之间通信的响应协议,它是用作客户端和服务器之间的请求. 客户端(浏览器)会向服务器提交HTTP请求:然后服务器向客户端返回响应 ...
最新文章
- CTOR在区块熵编码中的优点
- 机器学习梯度下降法举例
- java获取系统电量_android操作系统怎么获得电量
- C++继承中的普通函数,纯虚函数、虚函数
- 【python】set集合基础与使用
- 支付业务与技术架构学习总结(8)——支付系统设计包含:账户,对账,风控...
- 未来5年中国企业信息化格局
- NOIP 2014 解方程
- 「收藏」其实是欺骗自己
- 《我一开口,就能说服所有人》读书随记
- 使用数字全通滤波器对IIR滤波器进行相位补偿
- SRCNN 图像超分辨率重建(tf2)
- 【数据库系统】、【数据库】与【数据库管理系统】的区别
- 我是怎么做到开源系统中的文件上传等功能的?
- mpvue 搭配 minui
- [机器学习] 树模型(xgboost,lightgbm)特征重要性原理总结
- 软件测试工程师简历要怎么写,才能让 HR 看到?
- 日本测试人工智能破案,“机械战警”渐行渐近
- 视频按帧截取 python程序
- iTab!一款超级无敌好用的浏览器插件 简洁美观