http协议

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协议)