目录
Web应用中的基本单位是Web资源。Web资源分布在网络中的任意主机上,所以本机的浏览器要获取这些Web资源,就必须通过一种网络协议——HTTP协议。
HTTP协议是以Web资源为基本单位。
每次请求-响应只能针对一个Web资源进行。
HTTP: Hyper(超)Text (文本)Transfer(传输)Protocol(协议)
HTTP协议设计肇始,是为了传输超文本(HTML的前身),随着互联网的发展,HTTP协议传输的不仅仅是超文本了,目前其实任意类型都可以。围绕着超文本这套类型发展出来的前端三剑客(HTML、CSS、JavaScript)还是其主流;除此之外,其他多媒体资源也是非常常见的:图片、音频、视频等。
HTTP协议是一套应用层协议(一开始专注于业务,但现在HTTP协议本身也成为基础协议之一了),所以HTTP协议必须在一套传输层协议上进行传输。传输层的候选协议:UDP、TCP。
HTTP在1.0、1.1、2.0是基于TCP协议之上进行工作的。(HTTP协议中本身没有设计任何提供可靠性的机制,依赖传输层及以下网络已经提供可靠服务)
HTTP 在3.0之后,开始基于UDP协议上进行了。(HTTP协议内部自己做可靠性工作了)HTTP协议的客户端,一般称为浏览器,同时又被称为用户代理(User-Agent)等名称,网景浏览器可以说是最早的浏览器了。
Web资源:某些内容或者是执行一些动作,以服务的形式体现。购买一本书(书就是 web资源)、发个快递(发快递动作是web资源)。
重点是理解HTTP格式:请求格式和响应格式
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; /** * 只能进行一次请求-响应的 HTTP 客户端 */ public class MyHttpClient { public static void main(String[] args) throws IOException { // 主机 127.0.0.1 // 端口 8080 // 资源路径 /hello.html try (Socket socket = new Socket("127.0.0.1", 8080)) { // 准备 HTTP 请求内容 // 文本 String // 格式:请求行 String requestLine = "GET /hello.html HTTP/1.0\r\n"; // 请求头:完全可以没有,但必须一个空行结尾 // 请求头中共有 1对 key-value String requestHeader1 = "Name: xxx\r\n\r\n"; // 请求头中共有 2对 key-value String requestHeader2 = "Name: xxx\r\nAge: 1993\r\n\r\n"; // 请求头中共有 0 对 key-value String requestHeader3 = "\r\n"; // 请求体,GET 是没有请求体 // 最终的请求 —— 要发送给服务器的东西 String request = requestLine + requestHeader3; // 发送服务器的过程 byte[] requestBytes = request.getBytes("ISO-8859-1"); // 字符集编码 // 发送(数据会经由 TCP、IP、以太网发送给服务器) OutputStream os = socket.getOutputStream(); os.write(requestBytes); os.flush(); // 请求既然已经发送,我们要做的就是等待响应 InputStream is = socket.getInputStream(); // 响应的前面字符集应该是 ISO-8859-1,后边是 UTF-8 Scanner scanner = new Scanner(is, "UTF-8"); while (scanner.hasNextLine()) { String line = scanner.nextLine(); System.out.println(line); } } } }
import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class MyHttpServer { public static void main(String[] args) throws Exception { // 我们也监听在 8080 端口上 try (ServerSocket serverSocket = new ServerSocket(8080)) { while (true) { Socket socket = serverSocket.accept(); // 三次握手完成 // 读取用户的请求 :这里就不管用户的请求了,一律采用相同的方式返回响应 // 发送响应 // Content-Type: 浏览器应该按照什么格式来看到我们响应的资源内容的(资源内容放在响应体中) // 响应体(资源的内容) String responseBody = "Welcome MyHttpServer
"; byte[] responseBodyBytes = responseBody.getBytes("UTF-8"); int contentLength = responseBodyBytes.length; System.out.println("发送响应"); // 响应头 String response = "HTTP/1.0 200 OK\r\n" + "Server: xxx\r\n" + "Content-Type: text/plain; charset=utf-8\r\n" // 响应体的类型 + "Content-Length: " + contentLength + "\r\n" // 响应体的长度 + "\r\n"; byte[] responseBytes = response.getBytes("ISO-8859-1"); OutputStream os = socket.getOutputStream(); // TCP 是面向字节流的一种协议,所以只要按顺序发即可,不要管分几次发送 os.write(responseBytes); // 先发送前面部分(响应行 和 响应头) os.write(responseBodyBytes); // 再发送响应体 os.flush(); // 发送完成之后,直接关闭 TCP 连接(短连接的处理模式) socket.close(); } } } }
经常将ip(域名)+port 合起来称为主机 ( host)
1.请求方法
2.请求的资源路径3.请求版本
4.请求头
5.可能存在的请求体