1.HTTP协议:

  • Hyper Text Transfer Protocol:超文本传输协议
  • 基于TCP协议之上的请求/响应协议
  • 目前使用最广泛的高级协议
    * 使用浏览器浏览网页和服务器交互使用的就是HTTP协议
    * 手机应用上绝大多数程序与服务器之间交互数据使用的也是HTTP协议。
  • HTTP协议是一个纯文本协议
  • HTTP是一个请求/响应协议。浏览器发送一个请求,服务器收到以后,然后发送响应。

HTTP 1.0:

  • 每次请求都会创建一个新的HTTP连接,浏览器在请求一个网页之后,往往还是多次请求图片、CSS、JS等其他资源,而创建TCP连接需要一定的时间,所以HTTP1.0传输效率比较低

HTTP 1.1:
在HTTP1.0之上做了改进,多个HTTP请求可以通过一个TCP连接来完成。这样浏览器只需要和服务器建立一次TCP连接,就可以反复进行HTTP的请求/响应。它的效率比HTTP1.0要高

HTTP 2.0:
又对HTTP多了改进。多个HTTP请求也是通过一次TCP连接来完成的,但是浏览器在发送了一次HTTP请求以后,不需要等待响应,就可以立即发送第2个、第3个,而服务器在接收到请求的同时,又把前面已经接收的请求对应的响应发送出去,也就是说HTTP 2.0 请求/响应是可以异步发送的

2.HTTP请求格式

GET POST
请求 GET / HTTP/1.1 GET方法 路径 HTTP协议版本

Host: www.baidu.com 请求地址

User-Agent: Mozilla/5.0 (Linux; Android 9; ALP-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.89 Mobile Safari/537.36

User-Agent表示浏览器本身,如火狐

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3

Accept表示能接收什么样的数据

Accept-Language: zh-CN,zh;q=0.9 表示用户的语言
POST: /dataPipeline/uploadData?channel=statistics&version=v1 HTTP/1.1 请求方法 路径 HTTP协议类型

Host: cgicol.amap.com

User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; ALP-AL00 Build/HUAWEIALP-AL00)

Accept: */*

Accept-Language: zh-CN,zh,en

Content-Type: application/x-www-form-urlencoded 数据格式html表单

Content-Length: 264 数据长度264

channel=statistics&version=v1... Body具体的数据
响应 GET响应:HTTP/1.1 302 Found HTTP协议 响应

Content-Type:text/html;charset=utf-8 响应的内容是网页,编码是utf-8

Content-Length:0 响应的长度

响应体和header以空行分隔
HTTP/1.1 200

Content-Type: text/html;charset=ISO-8859-1 指定具体类型

Content-Length: 32086 大小

响应体

HTTP请求分为Header和Body2个部分,Header是必须的。Get请求只有Header没有Body,而Post请求既有Header,又有Body。Header和Body之间用一个空行分隔。
如果浏览器发送的是POST请求,那么浏览器还需要告诉服务器发送的数据格式Content-Type和数据的大小Content-Length,如application/x-www-form-urlencoded表示一个html表单,大小为264个字节。

HTTP响应也分为Header和Body2个部分,Header是必须的,第1行指出HTTP响应码。2XX正确返回,3XX重定向,4XX客户端错误,5XX服务器错误。
Header还可以包含各种属性,例如Content-Type指出Body的类型,Content-Length指出Body大小。
响应体通过一个空行与Header分隔,响应的数据可以是任意的文本或者二进制格式作为body。

HTTP Server

  • 处理HTTP请求,发送HTTP响应
  • 服务器是通过Java EE Servlet API来定义的

HTTP Client

  • 发送HTTP请求,接收HTTP响应
  • java.net.HttpURLConnection处理http的客户端

GET请求示例:

    URL url = new URL("http://www.exampe.com"); //获取URL对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //通过url对象的openConnection()获取HttpURLConnection对象
int code = conn.getResponseCode(); //获取响应码
try(InputStream input = conn.getInputSteam()){ //读取响应数据
//读取响应数据
}
conn.disconnect(); //断开连接

POST请求示例:

    URL url = new URL("http://www.example.com/login");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); //默认方法是get
conn.setDoOutput(true); //需要发送请求的数据
//指定数据的Content-Type和Content-Length
byte[] postData = "loginName=test&password=123456".getBytes("UTF-8");
conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length",String.valueOf(postData.length));
try(OutputStream output = conn.getOutputStream()){ //写入请求的数据
output.write(postData);
}
int code = conn.getResponseCode();
try(inputStream input = conn.getInputStream()){
//读取响应数据
}
conn.disconnect();

示例

package com.csj2018;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; class Response{
final int code;
final byte[] data;
public Response(int code,byte[] data){
this.code = code;
this.data = data;
}
@Override
public String toString(){
StringBuilder sb = new StringBuilder(1024);
sb.append("HTTP状态码").append(code).append("\n");
String s = new String(data,StandardCharsets.UTF_8);
if(s.length() > 100){
sb.append(s.substring(0,100)).append("\n...");
}else{
sb.append(s);
}
return sb.toString(); //返回状态码和前100个字节的内容,多于100,以...代表剩余内容
}
}
public class HttpClient {
public static void main(String[] args) throws Exception{
Response resp = get("http://www.douban.com");
System.out.println(resp);
Map<String,String> postMap = new HashMap<>();
postMap.put("form_email","test");
postMap.put("form_password","password");
Response postResp = post("https://www.douban.com/accounts/login","application/x-www-form-urlencoded",toFormData(postMap));
System.out.println(postResp);
}
static Response get(String theUrl){
System.err.println("GET:"+theUrl);
HttpURLConnection conn = null;
try{
URL url = new URL(theUrl); //获取URL对象
conn = (HttpURLConnection) url.openConnection(); //建立连接
ByteArrayOutputStream responseBuffer = new ByteArrayOutputStream(); //获取一个ByteArrayOutputStream对象用于存放读取的内容
try(InputStream input = conn.getInputStream()){//获取连接获取的内容
byte[] buffer = new byte[1024];
for(;;){
int n = input.read(buffer);
System.err.println("每次读取的大小:"+n);
if(n== (-1)){
break;
}
responseBuffer.write(buffer,0,n);//将内容写入到responseBuffer
System.out.println("每次写入后responseBuffer的大小"+responseBuffer.size());
}
}
return new Response(conn.getResponseCode(),responseBuffer.toByteArray());//返回Response对象
}catch (IOException e){
throw new RuntimeException(e);
}finally {
if(conn != null){
conn.disconnect();
}
}
}
static Response post(String theUrl,String contentType,String contentData){
System.err.println("POST:"+theUrl);
HttpURLConnection conn = null;
try{
URL url = new URL(theUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); //请求方法默认get,因此设为post
conn.setDoOutput(true);
//添加请求属性,Content-Type, Content-Length
conn.setRequestProperty("Content-Type",contentType);
conn.setRequestProperty("Content_Length",String.valueOf(contentData.length()));
//设置body
byte[] postData = contentData.getBytes(StandardCharsets.UTF_8); //
try(OutputStream output = conn.getOutputStream()){
output.write(postData);
}
ByteArrayOutputStream responseBuffer = new ByteArrayOutputStream();
try(InputStream input = conn.getInputStream()){
byte[] buffer = new byte[1024];
for(;;){
int n = input.read(buffer);
if(n==(-1)){
break;
}
responseBuffer.write(buffer,0,n);
}
}
return new Response(conn.getResponseCode(),responseBuffer.toByteArray());
}catch (IOException e){
throw new RuntimeException(e);
}finally {
if(conn != null){
conn.disconnect();
}
}
}
static String toFormData(Map<String,String> map) throws IOException{
List<String> list = new ArrayList<>(map.size());
for(String key:map.keySet()){
list.add(key + "=" + URLEncoder.encode(map.get(key),"UTF-8"));
}
return String.join("&",list); //key不编码,value编码,多个参数以&连接
}
}

3.总结:

  • HTTP协议是一个基于TCP的请求/响应协议
  • 广泛用于浏览器、手机app与服务器的数据交互
  • Java提供了HttpURLConnection实现HTTP客户端

廖雪峰Java13网络编程-3其他-1HTTP编程的更多相关文章

  1. 廖雪峰Java13网络编程-1Socket编程-2TCP编程

    1. Socket 在开发网络应用程序的时候,会遇到Socket这个概念. Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据 ...

  2. 廖雪峰Java13网络编程-3其他-2RMI远程调用

    1.RMI远程调用: Remote Method Invocation 目的:把一个接口方法暴露给远程 示例: 定义一个接口Clock,它有一个方法能够获取当前的时间,并编写一个实现类,来实现这个接口 ...

  3. 廖雪峰Java13网络编程-1Socket编程-5UDP编程

    1. UDP编程: 不需要建立连接 可以直接发送和接收数据 1.1 客户端 DatagramSocket sock = new DatagramSocket(){} sock.connect(addr ...

  4. 廖雪峰Java13网络编程-1Socket编程-3TCP多线程编程

    TCP多线程编程 一个ServerSocket可以和多个客户端同时建立连接,所以一个Server可以同时与多个客户端建立好的Socket进行双向通信. 因此服务器端,当我们打开一个Socket以后,通 ...

  5. 廖雪峰Java13网络编程-1Socket编程-1网络编程概念

    1.计算机网络 1.1 什么是计算机网络? 两台或更多计算机组成的网络 同一网络内的任意2台计算机都可以直接通信 所有计算机必须遵循同一种网络协议 1.2 什么是互联网 互联网是网络的网络 互联网采用 ...

  6. 廖雪峰Java13网络编程-2Email编程-2接收Email

    1接收Email协议类型 接收Email:收件人通过MUA软件把邮件从MDA抓取到本地计算机的过程. 1.1 POP3 从MUA到MDA使用最广泛的是协议是POP3 Post Office Proto ...

  7. 廖雪峰Java13网络编程-2Email编程-1发送email

    1.邮件发送 1.1传统邮件发送: 传统的邮件是通过邮局投递,从一个邮局到另一个邮局,最终到达用户的邮箱. 1.2电子邮件发送: 与传统邮件类似,它是从用户电脑的邮件软件(如outlook)发送到邮件 ...

  8. 廖雪峰Java1-3流程控制-9break、continue

    break跳出循环 int sum=0; for(int i=1; ;i++) { sum =sum + i; if(i == 100) { break; } } System.out.println ...

  9. 廖雪峰Java1-3流程控制-6 do-while循环

    do-while循环 do-while先执行循环,再判断条件. 条件满足时继续循环:条件不满足时退出:至少循环1次 int sum =0; int n = 1; do{ sum = sum + n; ...

随机推荐

  1. elementui tree 节点过滤加载对应子节点

    /官网例子 <el-input placeholder="输入关键字进行过滤" v-model="filterText"> </el-inpu ...

  2. java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)

    :: - [localhost-startStop-] INFO - Root WebApplicationContext: initialization started -- :: - [local ...

  3. 漏洞验证系列--MongoDB未授权访问

    本系列文章旨在对于有一定网络安全基础的人员,在日常工作中扫描出来的各种漏洞,如何进行验证,以区分该漏洞是否存在或是扫描器误报.请勿应用非法途径. 本漏洞是由于MongoDB未设置访问权限,用户可以直接 ...

  4. 15-MySQL-Ubuntu-数据表的查询-聚合函数(四)

    聚合函数 (1)count() 统计总数 查询男性总数 select count(*) as 男性 from students where gender=1; (2)max() 最大值 查询男性中年龄 ...

  5. Benchmark of Large-scale Unconstrained Face Recognition-blufr 算法的理解

    Many efforts have been made in recent years to tackle the unconstrained face recognition challenge. ...

  6. 整理下webapi的一些琐碎事情

    在使用webapi的时候我们会遇到一些问题比如 1.POST怎么请求 2.怎么兼容JSONP请求 3.怎么给指定端提供跨域的请求 4.怎么显示单独的models层的注释 问题一二其他人都玩的比较成熟的 ...

  7. zepto(mark)

    Zepto的设计目的是提供 jQuery 的类似的API,但并不是100%覆盖 jQuery .Zepto设计的目的是有一个5-10k的通用库.下载并快速执行.有一个熟悉通用的API,所以你能把你主要 ...

  8. python_django_models模块中的查询

    查询集:表示从数据库获取的对象集合,查询集可以有多个过滤器,过滤器就是一个函数(方法),基于所给参数限制查询集结果 从sql角度来说,查询集和select等价,过滤器和where等价 查询集特点: 惰 ...

  9. BCZM : 1.5

    https://blog.csdn.net/zs634134578/article/details/18046317 有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿 ...

  10. JavaScript - 常用对象相关

    1. String对象 length : 字符串的长度 charAt(index) : 返回指定位置的字符串, 下标从0开始 indexOf(str) : 返回指定的字符串在当前字符串中首次出现的位置 ...