Socket实现Http/Https请求

5,580 阅读2分钟

背景

OkHttp框架是基于Socket实现的,那么是怎么做到的呢?

1、Socket发起Http/Https Get请求

Http属于网络模型中的应用层,Socket属于传输层。Http请求是可以用Socket来实现的,只要Socket发出的请求格式按照Http协议规范,便是一个Http请求。那么Http请求的协议规范是什么样的呢?

1.1 Get请求报文格式

例如:

https://www.baidu.com?client=1

转换成一个Http请求报文如下:

GET /?client=1 HTTP/1.1
Host: www.baidu.com

1.2、Java代码实现Get请求

public static void main(String[] args) {
        try {
            //Https请求用SSLSocketFactory,如果是Http使用Socket
            Socket socket = SSLSocketFactory.getDefault().createSocket("www.baidu.com", 443);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //注意\r\n代表换行
            bw.write("GET /?client=1 HTTP/1.1\r\n");
            //这里第二个\r\n代表空行,空行是http协议里要求的,不能省略
            bw.write("Host: www.baidu.com\r\n\r\n");
            bw.flush();

            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while(true) {
                String readLine = null;
                if ((readLine = br.readLine()) != null) {
                    System.out.println(readLine);
                } else {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

1.3、Get请求带请求头

实际业务中,接口通常会带有token作为校验用户身份需要,那么这个请求头是怎么处理的呢?

GET /?client=1 HTTP/1.1
//请求属性集,写socket内容是写上token: 123456\r\n即可携带上
token: 123456
Host: www.baidu.com

1.4、小结

从上面的案例可以知道,用Socket发Http请求,只要在Socket输出流中写入满足Http协议规范的内容即可。

2、Socket发起Http/Https Post请求

2.1、案例:post请求

对应的报文如下:

POST /?client=1 HTTP/1.1
token: 123456
Content-Length: 7
Content-Type: application/json
Host: www.baidu.com

{"a":1}

和get请求的区别:post请求有两个多的固定字段,Content-Length和Content-Type,分别对应请求体的长度和类型,同时在Host字段后空行携带上请求体,而Get请求是不允许有请求体的

2.2、Java代码实现Post请求

private static void httpPost() {
        try {
            //Https请求用SSLSocketFactory,如果是Http使用Socket
            Socket socket = SSLSocketFactory.getDefault().createSocket("www.baidu.com", 443);
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("POST /?client=1 HTTP/1.1\r\n");
            bw.write("token: 123456\r\n");
            bw.write("Content-Length: 3\r\n");
            bw.write("Content-Type: application/json\r\n");
            bw.write("Host: www.baidu.com\r\n\r\n");
            bw.write("{\"a\":1}\r\n");
            bw.flush();

            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while(true) {
                String readLine = null;
                if ((readLine = br.readLine()) != null) {
                    System.out.println(readLine);
                } else {
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、Http报文格式

2.1、Http请求报文格式

2.2、Http响应报文格式

2.3、小结

使用Socket实现Http Get和Post请求,只要按照Http协议规范,在Socket OutPutStream中写入符合要求的内容即可,而解析响应和发起请求同理,按照格式解析即可获得响应内容