HTTP响应格式

HTTP请求格式

HTTP规定,HTTP请求由如下3部分组成:

  1. 请求方法、URI和HTTP版本;
  2. 请求头;
  3. 请求正文。

下面的代码是一个HTTP/1.1请求的例子。
GET /bird.gif HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: “Chromium”;v=“112”, “Google Chrome”;v=“112”, “Not:A-Brand”;v=“99”
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: “Windows”
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
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.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9

1.请求方式、URI和HTTP的版本

  HTTP请求的第一行包括请求方式、URI和协议版本3项内容,以空格分开:
GET /bird.gif HTTP/1.1
  在以上代码中,“GET”为请求方式,“/bird.gif”为URI,“HTTP/1.1”为HTTP的版本。
  根据HTTP协议,HTTP请求可以由多种方式,主要包括一下几种。

  1. GET:这种请求方式是最为常见的,客户程序通过这种方式访问服务器上的一个文档,服务器把文档发送给客户端。
  2. POST:客户程序可以通过这种方式发送大量信息给服务器。在HTTP请求中除了要访问的文档的URI,还包括大量的请求正文,这些请求正文中通常会包含HTML表单数据。
  3. HEAD:客户程序和服务器之间交流一下内部数据,服务器不会返回具体的文档。当使用GET和POST方法时,服务器最后都将特定的文档返回给客户程序。而HEAD请求方式则不同,它仅仅交流一些内部数据,这些数据不会影响用户浏览网页的过程,可以说对用户时透明的。HEAD请求方式通常不单独使用,而是对其他请求方式起辅助作用。一些搜索引擎使用HEAD请求方式来获得网页的标志信息,还有一些HTTP服务器进行安全认证时,用这个方式来传递认证信息。
  4. PUT:客户程序通过这种方式把文档上传给服务器。
  5. DELETE:客户程序通过这种方式来删除远程服务器上的某个文档。客户程序可以利用PUT和DELETE请求方式来管理远程服务器上的文档。
      GET和POST请求方式最常用,而PUT和DELETE请求方式并不常用,因此不少HTTP服务器不支持PUT和DELETE请求方式。
    统一资源定位符(Universal Resource Identifer,URI)用于标记要访问的网络资源。在HTTP请求中,通常只要给出相对于服务器根目录的相对目录即可,相对根目录以“/开头。
      HTTP请求的第一行的最后一部分内容为客户程序使用的HTTP请求。

2.请求头(Request Header)

  请求头包含许多有关客户端和请求正文的有用信息。例如,请求头可以声明浏览器的类型、所用语言、请求客户端系统平台等:
sec-ch-ua: “Chromium”;v=“112”, “Google Chrome”;v=“112”, “Not:A-Brand”;v=“99”
Accept-Language: zh-CN,zh;q=0.9
sec-ch-ua-platform: “Windows”

3.请求正文(Request Content)

  HTTP规定和请求正文之间必须空行分隔(即只有CRLN符号的行),这个空行非常重要,它表示请求头已经结束,接下来时请求正文。请求正文中可以包含客户以POST方式提交的表单数据,这个数据和请求头之间隔一行。

HTTP响应格式

和HTTP请求相似,HTTP响应也由3部分组成,分别是:

  1. HTTP的版本、状态码和描述;
  2. 响应头(Response Header);
  3. 响应正文(Response Content)。
    下面是一个HTTP/1.1响应的例子:
HTTP/1.1 200 ok
Content-Type:txt/html

<html>
<head>
<title>HelloWorld</title>
</head>
<body >
  <h1>Hello</h1>
</body>
</html>

1.HTTP的版本、状态码和描述

  HTTP响应的第一行包括服务器使用的HTTP的版本、状态代码,以及对状态码的描述,这3项内容之间以空格分隔。在本例中,使用HTTP/1.1协议,状态码为200,该状态代码表示服务器成功处理了客户端发出的请求:
HTTP/1.1 200 ok
状态码是一个3位整数,以1、2、3、4或5开头:

  • 1xx:信息提示,表示临时的响应。
  • 2xx:响应成功,表明服务器成功地接收了客户端请求。
  • 3xx:重定向。
  • 4xx:客户端错误,表明客户端可能有问题。
  • 5xx:服务器错误,表明客户端可能有问题。

以下是一些常见的状态代码:

  • 200:响应成功。
  • 400:错误的请求。客户端发送的HTTP请求不正确。
  • 404:文件不存在。在服务器上没有客户要访问的文档。
  • 405:服务器不支持客户的请求方式。
  • 500:服务器内部错误。

2.响应头(ResponseHeader)

  响应头也和请求头一样包含许多有用的信息,例如服务器类型、正文类型和正文长度等,如下所示:
Server:Apache-Coyote/1.1
Content-Type:txt/html
Content-Length:102

3.响应正文(Response Content)

  响应正文就是服务器返回的具体数据,它是浏览器正真请求访问的信息,最常见的是HTML文档,如下所示:

<html>
<head>
<title>HelloWorld</title>
</head>
<body >
  <h1>Hello</h1>
</body>
</html>

  HTTP请求头与请求正文之间必须用空行分隔,同样,HTTP响应头与响应正文之间也必须用空行分隔。
  当浏览器接收到HTTP请求后,会根据相应正文的不同类型来进行不同的处理。例如,对于大多数浏览器,如果响应正文是DOC文档,就会借助安装在本地的Word程序来打开这份DOC文档,如果响应正文是RAR压缩文档,就会弹出一个下载窗口让用户下载。

正文部分的MIME类型

  HTTP请求以及响应的正文部分可以是任意格式的数据,如何保证接收方能“看懂”发送方的正文数据呢?HTTP采用MIME协议来规范正文的数据格式。
  MIME协议由W3C组织制定,RFC2045文档(https://www.ietf.org/rfc/rfc2045.txt)对MIME协议做了详细阐述。MIME(Multipurpose Internet Mail Extension)是指多用途网络邮件扩展协议,这里的邮件不单纯地指E-Mail,还可以包括各种应用层协议在网络上传输地数据。因此,也可以将HTTP中的请求正文和响应正文看作邮件。
  遵从MIME协议地数据统称为MIME类型。在HTTP请求头和HTTP响应头中都有一个Content-type项,用来指定请求正文部分或响应正文部分地MIME类型。下表列出了常见的MIME类型与扩展名之间的对应关系。

文件扩展名MIME类型
未知的数据类型或不可识别的扩展名content/unknown
.bin、.exe、.o、.a、.zapplication/octet-stream
.pdfapplication/pdf
.zipapplication/zip
.tarapplication/x-tar
.gifimage/gif
.jpg、.jpegimage/jpeg
.htm、.htmltext/html
.text、.c、.h、.txt、.javatext/plain
.mpg、.mpegvideo/mpeg
.xmllapplication/xml

代码样例

HttpClient代码

package client;
import java.net.*;
import java.io.*;
import java.util.*;

public class HttpClient {
	public static void main(String args[])
	{
		//确定HTTP请求uri
		String uri = "hello1.htm";
		if(0 != args.length)uri = args[0];
		//按照GET请求方式访问HTTPServer
		doGet("localhost", 8080, uri);
	}
	
	//按照GET请求方式访问HTTPServer
	public static void doGet(String host, int port, String uri)
	{
		Socket socket = null;
		try {
			socket = new Socket(host, port);
		}catch(Exception e) {e.printStackTrace();}
		
		try {
			//创建HTTP请求
			StringBuffer sb = new StringBuffer("GET "+uri+" http/1.1\r\n");
			sb.append("Accept: */*\r\n");
			sb.append("Accept-Language:zh-cn\r\n");
			sb.append("Accept-Encoding:gzip,deflate\r\n");
			sb.append("User-Agent:HTTPClient\r\n");
			sb.append("Host:localhost:8080\r\n");
			sb.append("Connection:keep-Alive\r\n\r\n");
			
			//发送Http请求
			//获取输出流
			OutputStream socketOut = socket.getOutputStream();
			socketOut.write(sb.toString().getBytes());
			
			//睡眠2秒,等待响应结果
			Thread.sleep(2000);
			
			//接受响应结果
			//获取输入流
			InputStream socketIn = socket.getInputStream();
			int size = socketIn.available();
			byte[] buffer = new byte[size];
			socketIn.read(buffer);
			//打印响应结果
			System.out.println(new String(buffer));
		}catch(Exception e){e.printStackTrace();}
		finally {
			try {
				socket.close();
			}catch(Exception e) {e.printStackTrace();}
		}
	}
}

HttpServer代码

package server;

import java.io.*;
import java.net.*;

public class HttpServer {

	public static void main(String args[])
	{
		int port = 0;
		ServerSocket serverSocket;
		
		try {
			port = Integer.parseInt(args[0]);
		}
		catch (Exception e){
			System.out.println("port= 8080 默认");
			port = 8080;
		}
		
		try {
			serverSocket = new ServerSocket(port);
			System.out.println("服务器监听端口:"+serverSocket.getLocalPort());
			
			//服务器在一个无限循环钟不断接受来自客户端的TCP连接请求
			while(true)
			{
				try {
					//等待客户端的TCP连接请求
					final Socket socket = serverSocket.accept(); 
					System.out.println("建立了与客户的一个新的TCP连接,该客户的地址为:"+socket.getInetAddress()+":"+socket.getPort());
					//响应客户请求
					service(socket);
				}catch(Exception e) {
					System.out.println("客户端请求的资源不存在");
				}
			}
		}catch(Exception e) {e.printStackTrace();}
	}
	//响应HTTP请求信息
	public static void service(Socket socket)throws Exception{
		//读取HTTP的请求信息,获取输入流
		InputStream socketIn = socket.getInputStream();
		Thread.sleep(500); //睡眠500毫秒,等待HTTP请求
		int size = socketIn.available();
		byte[] buffer = new byte[size];
		socketIn.read(buffer);
		String request = new String(buffer);
		System.out.println(request); //打印HTTP请求数据内容
		
		//解析HTTP请求
		//获取HTTP请求的第一行
		int endIndex = request.indexOf("\r\n");
		if(-1 == endIndex)
			endIndex = request.length();
		String firstLineOfRequest = 
				request.substring(0, endIndex);
		
		//解析HTTP请求的第一行
		String[] parts = firstLineOfRequest.split(" ");
		String uri = "";
		if(2 <= parts.length)
		uri = parts[1]; //获取HTTP请求中的uri
		System.out.println("uri:"+uri);
		//决定HTTP响应正文的类型,此处做了简化处理
		String contentType;
		if(-1 != uri.indexOf("html")|| -1 != uri.indexOf("htm"))
			contentType = "txt/html";
		else if(-1 != uri.indexOf("jpg") || -1 == uri.indexOf("jpeg"))
			contentType = "image/jpeg";
		else if(-1 != uri.indexOf("gif"))
			contentType = "image/gif";
		else
			//字节流类型
			contentType = "application/octet-string";
		
		//创建HTTP响应结果
		//HTTP响应第一行
		String responseFirstLine = "HTTP/1.1 200 ok\r\n";
		//HTTP响应头
		String responseHeader = "Content-Type:"+contentType+"\r\n\r\n";
		//获得读取响应正文数据的输入流
		InputStream in;
		if(0 < uri.length() && '/' == uri.charAt(0))
		{
			in = HttpServer.class.getResourceAsStream("root"+uri);
			System.out.println("path:"+"root"+uri);
		}
		else
		{
			in = HttpServer.class.getResourceAsStream("root/"+uri);
			System.out.println("path:"+"root/"+uri);
		}
		//发送HTTP响应结果
		//获取输入流
		OutputStream socketOut = socket.getOutputStream();
		//发送HTTP响应结果
		socketOut.write(responseFirstLine.getBytes());
		//发送HTTP响应的第一行
		socketOut.write(responseHeader.getBytes());
		//发送HTTP响应正文
		int len = 0;
		buffer = new byte[128];
		while(-1 != (len = in.read(buffer)))
		socketOut.write(buffer, 0, len);
		
		//睡眠1秒
		Thread.sleep(1000);
		//关闭TCP连接
		socket.close();
	}
}

示例代码使用注意

  客户端请求的文件为hello1.htm,你需要在服务器端代码的class文件所在目录新建个root目录,再将文件放入该目录下,这样请求才能成功!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HTTP请求和响应消息都是由三个部分组成:起始行、消息头和消息体。下面分别介绍HTTP请求和响应消息的格式: 1. HTTP请求消息格式 HTTP请求消息格式如下: ``` Method Request-URI HTTP-Version Headers Message Body ``` 其中,Method表示请求方法(如GET、POST、PUT等),Request-URI表示请求的资源标识符,HTTP-Version表示HTTP协议的版本号,Headers是一些请求头信息,Message Body是请求消息的主体内容。 举个例子,如果要请求一个网页,请求消息可以这样构造: ``` GET /index.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 Accept: text/html,application/xhtml+xml ``` 其中,GET表示请求方法为GET,/index.html表示请求的资源为网站首页,HTTP/1.1表示使用HTTP协议的版本为1.1,Host表示请求的主机名为www.example.com,User-Agent表示浏览器类型为Mozilla/5.0,Accept表示可接受的响应类型为text/html、application/xhtml+xml等。 2. HTTP响应消息格式 HTTP响应消息格式如下: ``` HTTP-Version Status-Code Reason-Phrase Headers Message Body ``` 其中,HTTP-Version表示HTTP协议的版本号,Status-Code表示请求处理的状态码,Reason-Phrase表示状态码对应的原因短语,Headers是一些响应头信息,Message Body是响应消息的主体内容。 举个例子,如果服务器返回一个网页,响应消息可以这样构造: ``` HTTP/1.1 200 OK Date: Thu, 01 Jul 2021 06:17:30 GMT Server: Apache/2.2.22 Content-Type: text/html;charset=utf-8 <!DOCTYPE html> <html> <head> <title>My Web Page</title> </head> <body> <!-- 页面内容 --> </body> </html> ``` 其中,HTTP/1.1表示使用HTTP协议的版本为1.1,200表示响应处理的状态码为200,OK表示状态码对应的原因短语为“OK”。Date表示响应的时间,Server表示服务器类型为Apache/2.2.22,Content-Type表示响应的内容类型为text/html;charset=utf-8。Message Body中的内容是HTML文档,用于显示网页的内容。 以上是HTTP请求和响应消息的格式HTTP协议还有很多其他的特性和功能,需要根据具体的应用场景进行了解和学习。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值