Socket封装Http请求

2,343 阅读3分钟

前言

什么是Socket
它是计算机基于TCP/IP协议进行网络通信的基石。我们可以简单抽象的认为它是IP+端口号
它的本质是编程接口(API),对TCP/IP的封装。
了解Socket可以更好的帮助我们理解Http协议。

1 网络模型

网络架构模型主要有OSI参考模型和TCP/IP五层模型。 未命名文件.png 我们一般都是用的TCP/IP五层网络模型。
如图,应用层常见的网络协议有Http、Https、FTP等。传输层就两个,TCP、UDP。
主流的Http1.1也是基于TCP实现持久连接。

2 三次握手、四次挥手

了解了网络模型,我们可以再了解一下三次握手和四次挥手。
未命名文件.png

为什么需要三次握手?
其实很容易理解,当客户端请求连接,它不知道服务器是否做好了数据传输的准备,所以服务器需要返回信息说明自己准备好了。
收到信息后,客户端知道了服务器已经做好准备,基于可靠性而言,客户端需要再次发送确认信息,通知服务器,我收到了你的信息,准备开发数据传输。
就这么经过三次握手后,一条稳定的连接在客户端与服务器之间形成。

未命名文件 (1).png

四次挥手
首先客户端向服务器发送断开连接的请求(FIN)。
服务器收到后,不能立马断开连接,因为可能存在没有传输完的数据。所以基于可靠性而言,服务器先发送一个确认消息(告诉客户端,我收到你想断开连接的请求了,请稍等一下)。
服务器确认所有数据传输完毕后,发送断开连接请求。
客户端收到断开请求后,才真正得断开连接,发送确认消息给服务器,服务器这边也断开连接。

3 Http报文

http协议的请求报文

未命名文件 (2).png

示例:GET请求

GET /test HTTP/1.1
Host: 192.168.62.248:8080
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 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.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive

响应报文

企业微信截图_7c33cb59-8bcb-443c-8d8a-eab8902136f3.png

HTTP/1.1 200 
Content-Type: text/html;charset=UTF-8
Content-Length: 3
Date: Thu, 22 Apr 2021 06:15:51 GMT
Keep-Alive: timeout=60
Proxy-Connection: keep-alive

aaa

"aaa" 是服务器返回的响应数据。

4 Socket封装Http请求实现

了解基础的网络架构模型、三次握手、四次挥手、HTTP报文后,博主用socket封装请求,来实际证明HTTP报文结构如上图。

try {
    StringBuffer requestMessage = new StringBuffer(); // 请求报文
    requestMessage.append("GET / HTTP/1.0\r\n"); // 请求行
	// 省略请求头
    requestMessage.append("\r\n");
    // 省略正文

    // 通过socket建立连接,系统内核会完成三次握手
    Socket socket = new Socket();
    SocketAddress socketAddress = new InetSocketAddress("www.baidu.com", 80); // ip + port
    socket.connect(socketAddress); // 建立连接

    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    bufferedWriter.write(requestMessage.toString());
    bufferedWriter.flush();

    InputStream inputStream = socket.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    String line;
    while ((line = bufferedReader.readLine()) != null) {
        System.out.print(line + "\n");
    }
    inputStream.close();
} catch (IOException e) {
    e.printStackTrace();
}

程序运行结果
企业微信截图_cd26f8ac-bb12-442f-8549-a9c494d95531.png

小结

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
通过上面socket封装HTTP请求,想必各位已经对HTTP协议有了更深入的了解。
后续,如果想自定义协议进行通信,那么HTTP协议就是一个很棒的参考!