美文网首页
http协议

http协议

作者: xuefeng_apple | 来源:发表于2021-04-07 10:49 被阅读0次

    1-http 数据结构

    http 请求格式:(请求与响应有细微的差别)


    http 响应格式


    抓取包:


    2-http 参数说明

    查找某个资源
    URL:http://host[":"port][abs_path]
    HTTP协议的方法有:

    • GET: 请求获取Request-URI所标识的资源
    • POST: 在Request-URI所标识的资源后增加新的数据
    • HEAD: 请求获取由Request-URI所标识的资源的响应消息报头
    • PUT: 请求服务器存储或修改一个资源,并用Request-URI作为其标识
    • DELETE: 请求服务器删除Request-URI所标识的资源
    • TRACE: 请求服务器回送收到的请求信息,主要用于测试或诊断
    • CONNECT: 保留将来使用
    • OPTIONS: 请求查询服务器的性能,或者查询与资源相关的选项和需求

    http 消息包头【头key】




    状态行:
    由3部分组成,分别为:协议版本,状态码,状态码描述,之间由空格分隔
    状态码:为3位数字
    200-299的状态码表示成功
    300-399的状态码指资源重定向
    400-499的状态码指客户端请求出错
    500-599的状态码指服务端出错(HTTP/1.1向协议中引入了信息性状态码,范围为100-199)
    常见的:
    200:响应成功
    302:重定向跳转,跳转地址通过响应头中的Location属性指定
    400:客户端请求有语法错误,参数错误,不能被服务器识别
    403:服务器接收到请求,但是拒绝提供服务(认证失败)
    404:请求资源不存在
    500:服务器内部错误

    3-http简单使用例子(okhttp vs 自己写)

    HTTP的GET请求 [okhttp]

    //1,创建okHttpClient对象
    OkHttpClient mOkHttpClient = new OkHttpClient();
    //2,创建一个Request
    final Request request = new Request.Builder()
                    .url("https://www.baidu.com")
                    .build();
    //3,新建一个call对象
    Call call = mOkHttpClient.newCall(request); 
    //4,请求加入调度,这里是异步Get请求回调
    call.enqueue(new Callback()
            {
                @Override
                public void onFailure(Request request, IOException e)
                {
                }
    
                @Override
                public void onResponse(final Response response) throws IOException
                {
                        //String htmlStr =  response.body().string();
                }
            }); 
    

    不使用第三方库 http 方法
    server 与client 都是在android java 实现,举例调用了Socket.java的接口
    libcore/ojluni/src/main/java/java/net/Socket.java
    server 端

    • 第一步,启动服务端,监听本机 IP 和指定端口的客户端连接
    ServerSocket server = new ServerSocket();
    // 要监听的IP和端口
    SocketAddress address = new InetSocketAddress("192.168.1.111", 8888)
    server.bind(address);
    while (true) {
      Socket socket = server.accept();
      ... // 读取请求,发送响应
    }
    
    • 第二步,分发客户端请求,因为会有很多客户端来连接服务端,因此若在同一个线程内处理请求,服务端会忙不过来,我们启动一个新线程来处理请求:
    public class RequestHandler extends Thread {
        private Socket mSocket;
        public RequestHandler(Socket mSocket) {
            this.mSocket = mSocket;
        }
    
        @Override
        public void run() {
            ... // 读取请求,发送响应
        }
    }
    

    优化监听:

    while (true) {
      Socket socket = server.accept();
      System.out.println("---->>>> 发现客户端请求 <<<<----");
      RequestHandler handler = new RequestHandler(socket);
      handler.start();
    }
    
    • 第三步,简单的读取请求并打印请求数据&响应
    /**
     * 读取请求。
     */
    private void readRequest(Socket socket) throws IOException {
        InputStream is = socket.getInputStream();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[2048];
        int len;
        while ((len = is.read(buffer)) > 0) {
            bos.write(buffer, 0, len);
            if (len < 2048) break;
        }
        System.out.println(new String(bos.toByteArray()));
    }
    --------------------------------------------------------------
    /**
     * 发送响应。
     */
    private void sendResponse(Socket socket, byte[] data) throws IOException {
        OutputStream os = socket.getOutputStream();
        // 发送响应头
        PrintStream print = new PrintStream(os);
        print.println("HTTP/1.1 200 Beautiful");
        print.println("Server: HttpServer/1.0");
        print.println("Content-Length: " + data.length);
        print.println("Content-Type: text/plain; charset=utf-8");
        // 发送响应头和响应数据之间的换行
        print.println();
        // 发送响应数据
        print.write(data);
        os.flush();
    }
    

    上面run方法的实现:

    public class RequestHandler extends Thread {
      private static final Charset UTF8 = Charset.forName("utf-8");
        private Socket mSocket;
        public RequestHandler(Socket mSocket) {
            this.mSocket = mSocket;
        }
    
        @Override
        public void run() {
            readRequest(mSocket);
            String data = null;
            try {
              // 相当于服务端 HTTP API 处理业务,从数据库查数据等
              data = "test response";
            } catch(Exception e) {
               data = "test response two";
            }
            sendResponse(mSocket, data.getByte(UTF8));
            // 关闭Socket连接
            mSocket.close();
        }
    }
    

    client端

    • 第一步,使用 Socket 建立和服务端的连接
    // 要连接的主机域名和端口
    InetSocketAddress address = new InetSocketAddress("192.168.1.111", 8888);
    // 建立连接
    Socket socket = new Socket();
    socket.setSoTimeout(10 * 1000);
    socket.connect(address, 10 * 1000);
    
    • 第二步,按照格式发送请求头、换行和请求数据
    // 发送请求头
    PrintStream print = new PrintStream(socket.getOutputStream());
    print.println("POST /abc/dev?ab=cdf HTTP/1.1");
    print.println("Host: 192.168.1.111:8888");
    print.println("User-Agent: HttpClient/1.0");
    print.println("Content-Length: 15");
    print.println("Accept: *");
    // 发送请求头和请求数据之间的换行
    print.println();
    // 发送请求数据
    print.println("恰同学少年");
    
    • 第三步,简单的读取响应并打印响应数据
    InputStream is = socket.getInputStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] buffer = new byte[2048];
    int len;
    while ((len = is.read(buffer)) > 0) {
      bos.write(buffer, 0, len);
      if (len < 2048) break;
    }
    String body = new String(bos.toByteArray());
    System.out.println(body);
    

    REF:
    https://www.jianshu.com/p/f3f228d3598c
    https://yanzhenjie.blog.csdn.net/article/details/93098495

    相关文章

      网友评论

          本文标题:http协议

          本文链接:https://www.haomeiwen.com/subject/djbykltx.html