理解Http协议(一)
本文对Http协议进行了简要的描述,说明了其用途的广泛性;通过代码对Http连接和Http请求消息的发送进行实现,希望能将这些抽象的过程直观的显示出来;最后对HttpURL和Http协议中“资源”这些相对抽象概念进行描述和举例。
网络协议是指为计算机网络中进行数据交换而建立的规则、标准或约定的集合。Http协议是一种应用层协议,能用于构建分布式协作的超媒体信息系统。作为一种通用的无状态的协议,Http不仅能用于超文本的传输,也能用于名称服务器,分布式对象管理系统。HTTP的其中一个特征就是能对数据的表示形式进行分类和协商,因此能够建立独立于数据传输的各种系统。除了用于html网页,javascript脚本等文件的传输及其它文件的上传下载;也能通过HTTP协议开放Web服务的api,诸如亚马逊,FACEBOOK等公司提供基于Http开放自身的服务api;还有像Solr这样的全文检索服务器,通过运行于Web服务器,通过Http传输数据。HTTP的目的是提供多样的可扩展的多种配置选项,达到能Web应用提供高可靠性,至少在服务失败的情况下提供可靠地报错的目的,这样的Web应用可以是运行于高带宽的企业内部网的或者是手持设备接入的低带宽传输链路的环境(协议上的一段翻译,不明觉厉,他们说是这样就是吧,我们可以理解为了达到这样的效果,协议内部定义了不少细节)。Http协议定义的细节,包括了诸如:客户端请求消息格式、服务端应答消息格式、服务应答消息状态码以及像GET或POST的多种请求方法等等细节。更具体的内容见:http://en.wikipedia.org/wiki/List_of_HTTP_headers 和 http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol。
一 、Http请求消息格式及Http连接
Http是基于请求/响应的协议,即客户端向服务端发送请求消息,服务端给与应答。
Http请求消息依次包括几个部分:请求行(以CRLF结尾,CR为回车符,LF为换行符,两者使用US-ASCII编码,分别是'\r','\n'),请求头部(以CRLF结尾),空行(CRLF),消息主体(其他请求方法可选,在POST方法必须用到)。请求头部以及请求行是由字符串组成,这一部分的字符串编码要求使用US-ASCII编码。
下图使用Chrome浏览器自带的开发者工具捕捉到的一个HTTP请求消息:
请求消息的请求行:
请求行由以下几部分依次组成,请求方法(如:GET、POST、HEAD等);Request-URI,标志请求资源的字符串,可以有如http://www.w3.org/pub/WWW/TheProject.html 或 /pub/WWW/TheProject.html两种表示方法;协议版本:HTTP/1.1 或HTTP/1.0;最后以CRLF(使用US-ASCII编码的'\r','\n'两个字符)结尾。
请求头部:
请求头部能够传递额外的客户端信息,是由请求头部字段及字段对应值组成的键值对,并且是可扩展的,字段名称和字段值使用冒号分开,并且使用CRLF作为结尾。
最后请求消息可以带有消息主体,消息主体的解析由自身应用逻辑进行处理。服务端接收解析请求消息,将回应Http应答信息,应答信息由状态行、应答头部、空行及消息主体组成。
Http连接
Http通常建立在TCP连接上,但是协议中并没有规定必须使用TCP,HTTP建立在下层提供可靠的传输协议之上。因此,任何能够提供这种保证的协议都可以被其使用。服务端通常开放端口80,提供Http服务。
具备了对Http请求消息以及Http连接的基本知识,我们可以通过Socket编程简单实现这一协议;实现步骤如下:向服务主机建立起TCP连接,端口为80;发送请求消息;读取服务端输出,向控制台输出服务端的输出。
以下是Java代码的实现:
package http; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.Charset; public class HttpTest { public static void main(String[] args) {
// Http请求头部的字符串表示;
String requestMessage="GET / HTTP/1.1\r\n"+
"Host: www.w3.org\r\n"+
"Connection: keep-alive\r\n"+
"\r\n";
//服务器主机名
String hostName="www.w3.org";
Socket tcpSocket=new Socket();
//指定所要连接的服务端端口为80
InetSocketAddress hostAddr=new InetSocketAddress(hostName,80);
try {
tcpSocket.connect(hostAddr);
//获取向该连接写入的输出流
OutputStream outputStream=tcpSocket.getOutputStream();
//Http请求消息的编码为US-ASCII;由于不同字符编码中可能在一些字符二进制表示重叠,因此
//不指定编码也可能产生正确的结果但不够准确的。
byte[] bytes=requestMessage.getBytes(Charset.forName("US-ASCII"));
outputStream.write(bytes);
//获取该连接的输入流,可以读取流中的数据
InputStream inputStream=tcpSocket.getInputStream();
byte[] buffer=new byte[128];
int n=inputStream.read(buffer);
while(n>0)
{
//这里将读取的二进制流转化成字符串,这里的实现没有考虑到二进制流的边界是否能够
//刚好转化为字符串的问题,但是由于都是英文所以这里也不会出现乱码问题,UTF-8为该网页选择的编码
String str=new String(buffer,0,n,Charset.forName("UTF-8"));
System.out.print(str);
n=inputStream.read(buffer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*程序的部分输出:
HTTP/1.1 200 OK
Date: Sat, 15 Feb 2014 07:08:30 GMT
Server: Apache/2
Content-Location: Home.html
Vary: negotiate,accept
TCN: choice
Last-Modified: Sat, 15 Feb 2014 05:00:19 GMT
ETag: "967f-4f26acc8b9ec0;89-3f26bd17a2f00"
Accept-Ranges: bytes
Content-Length: 38527
Cache-Control: max-age=600
Expires: Sat, 15 Feb 2014 07:18:30 GMT
P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
Content-Type: text/html; charset=utf-8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- Generated from data/head-home.php, ../../smarty/{head.tpl} -->
<head>
*/
我们也可以使用telnet工具模拟这一过程,Telnet是Internet远端登录服务的一个协议;建立在TCP连接之上,这里我们可以借助它建立TCP连接,并发送HTTP请求消息。
二、什么是HttpURL和Http协议中的资源?
URL(Uniform Resource Locator,统一资源定位符),用于标志网络上某个资源的地址,而URI(Uniform Resource Identifier,统一资源标识符)是一个用于标识某一互联网资源名称的字符串,其内涵包括URL和URN(Uniform Resource Name,统一资源名称)。URN定义某事物的身份,而URL提供查找该事物的方法。可以认为统一资源名(URN)如同一个人的名称,而统一资源定位符(URL)代表一个人的住址。这里的资源可以理解为某个数据对象,如:某个html文档;js脚本文件;或者是某种服务,如查询服务,然后可以以json或xml格式返回结果。协议指出通过HTTP协议请求的资源由URI来标识。笔者没有接触过URN和HTTP协议相结合的东西,因此本文只讨论HttpURL的东西。
一个URL由两个部分组成:
(1)协议标志符:对于URL http://example.com ,http便是该URL的协议标志符;意味着使用该协议所规定的内容访问资源。
(2)资源名称: 对于 URL http://example.com ,资源名称为 “example.com”。
HttpURL的格式如下:
http_URL = "http:""//" host [ ":" port ] [ abs_path [ "?" query ]]
其中http: 和"//"为文字常量,host为服务端的主机名也可以是服务端的IP(协议建议尽量不用IP地址),port为可选的选项,可以指定值,或者采用默认的端口80,即访问服务端的80端口。
abs_path指定主机上的某个资源路径。如:http://www.telnet.org/htm/dev.htm中的/htm/dev,如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,底层代码实现必须指定为“/";通常这个工作浏览器自动帮我们完成。
例如:
输入:www.guet.edu.cn此时浏览器自动转换成:http://www.guet.edu.cn/ (例子来源于:http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html );也就是在请求行是 GET / HTTP/1.1。
对于HttpURL来说,"Http",意味着以Http协议来访问资源,从实现的角度来说也就是,底层建立起TCP连接,连接服务器端口port,服务器名为HttpURL字符串中的host,然后发送连接的消息;也就是HttpURL将建立TCP连接和发送请求消息,还有可以对接收服务端返回的应答消息进行一定解析这些过程进行抽象,Java API提供了抽象类java.net.HttpURLConnection和类java.net.URL中的openConnection()支持这写过程,以下是使用这两个类进行http连接的代码,最后将服务端的应答消息输出至控制台:
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset; public class HttpURLTest { public static void main(String[] args) throws MalformedURLException {
// 指定HttpURL字符串构建URL对象;格式错误的话抛出MalformedURLException
URL httpURL=new URL("http://www.w3c.org/");
try {
//打开连接,将返回的URLConnection向下转化为HttpConnection
//由于我们指定了http协议访问,因而这样的转型是安全的
HttpURLConnection httpConn=(HttpURLConnection)httpURL.openConnection();
//HttpURLConnection将Http协议的一些细节进行抽象,因此我们可以很方便的得到应答消息的
//状态码;
System.out.println("response code="+httpConn.getResponseCode());
InputStream inputStream=httpConn.getInputStream();
byte[] buffer=new byte[128];
int n=inputStream.read(buffer);
while(n>0)
{
//这里将读取的二进制流转化成字符串,这里的实现没有考虑到二进制流的边界是否能够
//刚好转化为字符串的问题,但是由于都是英文所以这里也不会出现乱码问题,UTF-8为该网页选择的编码
String str=new String(buffer,0,n,Charset.forName("UTF-8"));
System.out.print(str);
n=inputStream.read(buffer);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*程序的部分输出:
response code=200
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<!-- Generated from data/head-home.php, ../../smarty/{head.tpl} -->
<head>
<title>World Wide Web Consortium (W3C)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="Help" href="/Help/" />
<link rel="stylesheet" href="/2008/site/css/minimum" type="text/css" media="handheld, all" />
<style type="text/css" media="print, screen and (min-width: 481px)">
*/
理解Http协议(一)的更多相关文章
- 转载和积累系列 - 深入理解HTTP协议
深入理解HTTP协议 1. 基础概念篇 1.1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(World Wide Web C ...
- 爬虫入门系列(一):快速理解HTTP协议
4月份给自己挖一个爬虫系列的坑,主要涉及HTTP 协议.正则表达式.爬虫框架 Scrapy.消息队列.数据库等内容. 爬虫的基本原理是模拟浏览器进行 HTTP 请求,理解 HTTP 协议是写爬虫的必备 ...
- 深入理解AMQP协议
深入理解AMQP协议 2018年10月22日 12:32:16 一剑何风情 阅读数:1941 文章目录 一.AMQP 是什么 二.AMQP模型 工作过程 深入理解 三.Exchange交换机 默认 ...
- 网络编程懒人入门(六):深入浅出,全面理解HTTP协议
本文引用了自简书作者“涤生_Woo”的文章,内容有删减,感谢原作者的分享. 1.前言 HTTP(全称超文本传输协议,英文全称HyperText Transfer Protocol)是互联网上应用最为广 ...
- [搜狐科技]由浅入深理解Raft协议
由浅入深理解Raft协议 2017-10-16 12:12操作系统/设计 0 - Raft协议和Paxos的因缘 读过Raft论文<In Search of an Understandable ...
- (转存 作者未知)深入理解HTML协议
深入理解HTML协议 http协议学 习系列 1. 基础概念篇 1.1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(Worl ...
- 3. 与服务器对话:理解 HTTP 协议
0.服务器与本地交换机制 2.详解HTtp服务 (1)与服务器对话的流程 (2)Reque 请求 (3)Response 响应 200 成功 404 没有网页 (4)Get/Post区别 get查询数 ...
- 全面理解HTTP协议
引言:作为一名软件工程Web专业学生,对于HTTP的熟悉掌握是必不可少的,特此做记录,打造自己的HTTP栈. URL与URI 我们经常接触到的就是URL了,它就是我们访问web的一个字符串地址,那么U ...
- 深入理解 web 协议(一)- http 包体传输
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/WlT8070LlrnSODFRDwZsUQ作者:吴越 开坑这个系列的原因,主要是在大前端学习的 ...
- 转战物联网·基础篇05-通俗理解MQTT协议的实现原理和异步方式
网络上搜索MQTT协议,会出现太多的解释,这里就不做官方标准释义的复制了.这一节我们从实战理解角度,通俗的将MQTT协议的作用及实现原理说一下,旨在可以快速理解MQTT协议.所以可能会出现很多看似 ...
随机推荐
- POJ1838
poj 1838 这道题主要是对并查集的考察,在这道题的解题过程中主要用到的算法就是并查集中的最基本的makeSet,findSet,unionSet 即前篇文章中所提到的: makeSet(Elem ...
- mysql实用指南
mysqld --verbose --help: 可以显示 mysql 的编译配置选项,即功能配置描述. mysql 的配置文件my.cnf调用次序(mysqld --verbose --help 的 ...
- system partition table
转载内容 摘录部分我的笔记的中doc,和大家一起感受Oracle 11g在分区方面的增强--System Partitioning 系统分区的特点 ●系统分区与其他分区相比,一个最根本的区别就是不需要 ...
- PAT 1089. Insert or Merge (25)
According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...
- testlink邮件设置(centos 7)
上一篇文章在centos 7上安装了testlink(CentOS 7下安装xampp和testlink),本篇进行邮件设置,可在进行testlink密码修改.用例指派时进行邮件通知 1.修改conf ...
- [Angular 2] ROUTING IN ANGULAR 2 REVISITED
Let's say we have a list of contacts, click each contact, we can render a new route to get the detai ...
- SNMP协议总结
说明:本文仅供学习交流,转载请标明出处,欢迎转载! SNMP(Simple Network Management Protocal),简单网络管理协议,其前身是SGMP协议(简单网关监控协议),该协议 ...
- MySQL 权限?
一.权限表 mysql数据库中的3个权限表:user .db. host 权限表的存取过程是: 1)先从user表中的host. user. password这3个字段中判断连接的IP.用户名.密码是 ...
- iOS开发中常用到的加密方式
1 base64 1.1 简介 Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码.它将需要编码的数据拆分成字节数组.以3个字节为一组.按顺序排列24位数据,再把这24位数据 ...
- Java基础知识强化之集合框架笔记65:Map集合之集合多层嵌套的数据分析
1. 为了更符合要求: 这次的数据就看成是学生对象. 传智播客 bj 北京校区 jc 基础班 林青霞 27 风清扬 30 jy 就业班 赵雅芝 28 武鑫 29 sh 上海 ...