HTTP报文由从客户机到服务器的请求和从服务器到客户机的响应构成。
- HTTP请求报文格式:请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体
请求行:包括请求方式Method、资源路径URL、协议版本Version;
请求头:包括一些访问的域名、用户代理、Cookie等信息;
请求正文:就是HTTP请求的数据。即url链接参数
- HTTP应答报文格式:状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体
状态行:包括协议版本Version、状态码Status Code、回应短语;
常见状态码表示含义如下:
200---OK/请求已经正常处理完
301---/请求永久重定向 302---/请求临时重定向 304---/请求被重定向到客户端本地缓存
400---/客户端请求存在语法错误 401---/客户端请求没有经过授权 403---/客户端的请求被服务器拒绝,一般为客户端没有访问权限 404---/客户端请求的URL在服务端不存在
500---/服务端永久错误 503---/服务端发生临时错误
响应头:包括搭建服务器的软件,发送响应的时间,回应数据的格式等信息;
响应正文:就是响应的具体数据。
- 这里用java实现客户端简单的HTTP请求
private String httpRequest(String urlStr) {
StringBuffer strBuffer;
try {
//创建url对象
URL url = new URL(urlStr);
//获取连接对象
URLConnection conn = url.openConnection();
//设置url连接数据可读
conn.setDoInput(true);
//设置url链接参数可写
conn.setDoOutput(true);
//建立通信
conn.connect();
// 得到输入流
InputStream in = conn.getInputStream();
InputStreamReader reader = new InputStreamReader(in, "utf-8");
BufferedReader br = new BufferedReader(reader);
strBuffer = new StringBuffer();
String line = null;
while(null != (line = br.readLine())) {
strBuffer.append(line);
}
if(in !=null & reader != null & br != null) {
in.close();
reader.close();
br.close();
}
return strBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
- 利用HttpClient实现请求
- HttpClient简介
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
HttpClient下载地址 http://hc.apache.org/downloads.cgi
2. 使用即实现如下:
/**
* 利用commons-httpclient API 实现get/post有参或无参请求
* @method request
* @param urlStr http://www.baidu.com 或hhtps...
* @param method get/post
* @param map null无参/key-value键值对参数
* @return 响应文本
* String
*/
public String request(String urlStr,String method,Map<String,Object> map) {
if(method == "get") {
// 创建httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
URIBuilder uriBuilder = new URIBuilder(urlStr);
if( null != map) {
Set<String> params = map.keySet();
for(String param:params) {
uriBuilder.addParameter(param, (String) map.get(param));
}
}
// 创建get请求对象
HttpGet get = new HttpGet(uriBuilder.build());
CloseableHttpResponse response = httpClient.execute(get);
// 得到服务器响应码 200为通
//int statuCode = response.getStatusLine().getStatusCode();
//System.out.println(statuCode);
// 获得响应实体
HttpEntity entity = response.getEntity();
// 响应正文
String text = EntityUtils.toString(entity,"utf-8");
// 关闭响应
response.close();
return text;
} catch (Exception e) {
e.printStackTrace();
}finally {
if( null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if(method == "post") {
CloseableHttpClient httpClient = HttpClients.createDefault();
//https://www.imooc.com/course/list?c=java 列如urlStr=//https://www.imooc.com/course/list
HttpPost post = new HttpPost(urlStr);
try {
// 添加参数
if(null != map) {
List<NameValuePair> paramList = new ArrayList<NameValuePair>();
// 所有参数列表key值 hashset不重复
Set<String> keys = map.keySet();;
//paramList.add(new BasicNameValuePair("c", "java")); 添加参数
for(String key:keys) {
paramList.add(new BasicNameValuePair(key,(String)map.get(key)));
}
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
post.setEntity(entity);
}
//System.out.println(post.getURI().toString());
HttpResponse response = httpClient.execute(post);
int statuCode = response.getStatusLine().getStatusCode();
System.out.println(statuCode);
// 得到的响应文本
String text = EntityUtils.toString(response.getEntity());
//System.out.println(text);
return text;
} catch (Exception e) {
e.printStackTrace();
}finally {
if( null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
return null;
}
- HTTP协议历史:
HTTP/0.9
HTTP协议的最初版本,功能简陋,仅支持请求方式GET,并且仅能请求访问HTML格式的资源。
HTTP/1.0
在0.9版本上做了进步,增加了请求方式POST和HEAD;不再局限于0.9版本的HTML格式,根据Content-Type可以支持多种数据格式,即MIME多用途互联网邮件扩展,例如text/html、image/jpeg等;同时也开始支持cache,就是当客户端在规定时间内访问统一网站,直接访问cache即可。
但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接,就是不支持keepalive。
HTTP/1.1
解决了1.0版本的keepalive问题,1.1版本加入了持久连接,一个TCP连接可以允许多个HTTP请求; 加入了管道机制,一个TCP连接同时允许多个请求同时发送,增加了并发性;新增了请求方式PUT、PATCH、DELETE等。
但是还存在一些问题,服务端是按队列顺序处理请求的,假如一个请求处理时间很长,则会导致后边的请求无法处理,这样就造成了队头阻塞的问题;同时HTTP是无状态的连接,因此每次请求都需要添加重复的字段,降低了带宽的利用率。
HTTP/2.0
为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。增加双工模式,即不仅客户端能够同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题;HTTP请求和响应中,状态行和请求/响应头都是些信息字段,并没有真正的数据,因此在2.0版本中将所有的信息字段建立一张表,为表中的每个字段建立索引,客户端和服务端共同使用这个表,他们之间就以索引号来表示信息字段,这样就避免了1.0旧版本的重复繁琐的字段,并以压缩的方式传输,提高利用率。
另外也增加服务器推送的功能,即不经请求服务端主动向客户端发送数据。
目前主流的协议版本还是HTTP/1.1版本。