目录
1.HTTP协议简介
HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一个简单的请求-响应协议,HTTP通常运行在TCP之上。
在编写网络通信代码时,我们可以自己进行协议的定制,但实际有很多优秀的工程师早就已经写出了许多非常成熟的应用层协议,其中最典型的就是HTTP协议。
2.认识URL
URL(Uniform Resource Lacator)叫做统一资源定位符,也就是我们通常所说的网址,是因特网的万维网服务程序上用于指定信息位置的表示方法。
一个URL大致由如下几部分构成:
协议方案名
http:// 表示的是协议名称,表示请求时需要使用的协议,通常使用的是HTTP协议或安全协议HTTPS。HTTPS是以安全为目标的HTTP通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性。
常见的应用层协议:
- DNS(Domain Name System)协议:域名系统。
- FTP(File Transfer Protocol)协议:文件传输协议。
- TELNET(Telnet)协议:远程终端协议。
- HTTP(Hyper Text Transfer Protocol)协议:超文本传输协议。
- HTTPS(Hyper Text Transfer Protocol over SecureSocket Layer)协议:安全数据传输协议。
- SMTP(Simple Mail Transfer Protocol)协议:电子邮件传输协议。
- POP3(Post Office Protocol - Version 3)协议:邮件读取协议。
- SNMP(Simple Network Management Protocol)协议:简单网络管理协议。
- TFTP(Trivial File Transfer Protocol)协议:简单文件传输协议。
登录信息
usr:pass表示的是登录认证信息,包括登录用户的用户名和密码。虽然登录认证信息可以在URL中体现出来,但绝大多数URL的这个字段都是被省略的,因为登录信息可以通过其他方案交付给服务器。
服务器地址
www.example.jp 表示的是服务器地址,也叫做域名,比如www.alibaba.com,www.qq.com,www.baidu.com。
需要注意的是,我们用IP地址标识公网内的一台主机,但IP地址本身并不适合给用户看。比如说我们可以通过ping命令,分别获得www.baidu.com和www.qq.com这两个域名解析后的IP地址。
如果用户看到的是这两个IP地址,那么用户在访问这个网站之前并不知道这两个网站到底是干什么的,但如果用户看到的是www.baidu.com和www.qq.com这两个域名,那么用户至少知道这两个网站分别对应的是哪家公司,因此域名具有更好的自描述性。
实际我们可以认为域名和IP地址是等价的,在计算机当中使用的时候既可以使用域名,也可以使用IP地址。但URL呈现出来是可以让用户看到的,因此URL当中是以域名的形式表示服务器地址的。
服务器端口号
80表示的是服务器端口号。HTTP协议和套接字编程一样都是位于应用层的,在进行套接字编程时我们需要给服务器绑定对应的IP和端口,而这里的应用层协议也同样需要有明确的端口号。
常见协议对应的端口号:
协议名称 | 对应端口号 |
---|---|
HTTP | 80 |
HTTPS | 443 |
SSH | 22 |
当我们使用某种协议时,该协议实际就是在为我们提供服务,现在这些常用的服务与端口号之间的对应关系都是明确的,所以我们在使用某种协议时实际是不需要指明该协议对应的端口号的,因此在URL当中,服务器的端口号一般也是被省略的。
server端的port是不能随意指定的,必须是众所周知且不能随便修改的端口号和成熟的应用层协议是一一对应的;协议名称和端口号是1对1强相关的,所以一个服务端的公司的端口号需要进行统一的管理。
带层次的文件路径
/dir/index.htm表示的是要访问的资源所在的路径。访问服务器的目的是获取服务器上的某种资源,通过前面的域名和端口已经能够找到对应的服务器进程了,此时要做的就是指明该资源所在的路径。
比如我们打开浏览器输入百度的域名后,此时浏览器就帮我们获取到了百度的首页。
当我们发起网页请求时,本质是获得了这样的一张网页信息,然后浏览器对这张网页信息进行解释,最后就呈现出了对应的网页。
我们可以将这种资源称为网页资源,此外我们还会向服务器请求视频、音频、网页、图片等资源。HTTP之所以叫做超文本传输协议,而不叫做文本传输协议,就是因为有很多资源实际并不是普通的文本资源。
因此在URL当中就有这样一个字段,用于表示要访问的资源所在的路径。此外我们可以看到,这里的路径分隔符是/,而不是\,这也就证明了实际很多服务都是部署在Linux上的
查询字符串
uid=1表示的是请求时提供的额外的参数,这些参数是以键值对的形式,通过&符号分隔开的。
比如我们在百度上面搜索HTTP,此时可以看到URL中有很多参数,而在这众多的参数当中有一个参数wd(word),表示的就是我们搜索时的搜索关键字wd=hellolinux。
因此双方在进行网络通信时,是能够通过URL进行用户数据传送的。
片段标识符
ch1表示的是片段标识符,是对资源的部分补充。
比如我们在看组图的时候,URL当中就会出现片段标识符。
当我们在翻看组图时,这个片段标识符就会发生变化。
3.urlencode和urldecode
如果在搜索关键字当中出现了像/?:这样的字符,由于这些字符已经被URL当作特殊意义理解了,因此URL在呈现时会对这些特殊字符进行转义。
其实就是将特殊字符转化为16进制,实际当服务器拿到对应的URL后,也需要对编码后的参数进行解码,此时服务器才能拿到你想要传递的参数,解码实际就是编码的逆过程。
4.HTTP请求协议和响应协议
应用层常见的协议有HTTP和HTTPS,传输层常见的协议有TCP,网络层常见的协议是IP,数据链路层对应就是MAC帧了。其中下三层是由操作系统或者驱动帮我们完成的,它们主要负责的是通信细节。如果应用层不考虑下三层,在应用层自己的心目当中,它就可以认为自己是在和对方的应用层在直接进行数据交互。
下三层负责的是通信细节,而应用层负责的是如何使用传输过来的数据,两台主机在进行通信的时候,应用层的数据能够成功交给对端应用层,因为网络协议栈的下三层已经负责完成了这样的通信细节,而如何使用传输过来的数据就需要我们去定制协议,这里最典型的就是HTTP协议。
HTTP是基于请求和响应的应用层服务,作为客户端,你可以向服务器发起request,服务器收到这个request后,会对这个request做数据分析,得出你想要访问什么资源,然后服务器再构建response,完成这一次HTTP的请求。这种基于request&response这样的工作方式,我们称之为cs或bs模式,其中c表示client,s表示server,b表示browser。
HTTP请求协议
HTTP请求由以下四部分组成:
- 请求行:[请求方法]+[url]+[http版本]
- 请求报头:请求的属性,这些属性都是以key: value的形式按行陈列的。
- 空行:遇到空行表示请求报头结束。
- 请求正文:请求正文允许为空字符串,如果请求正文存在,则在请求报头中会有一个Content-Length属性来标识请求正文的长度。
- 其中,前面三部分是一般是HTTP协议自带的,是由HTTP协议自行设置的,而请求正文一般是用户的相关信息或数据,如果用户在请求时没有信息要上传给服务器,此时请求正文就为空字符串。
HTTP响应协议
HTTP响应由以下四部分组成:
- 状态行:[http版本]+[状态码]+[状态码描述]
- 响应报头:响应的属性,这些属性都是以key: value的形式按行陈列的。
- 空行:遇到空行表示响应报头结束。
- 响应正文:响应正文允许为空字符串,如果响应正文存在,则响应报头中会有一个Content-Length属性来标识响应正文的长度。比如服务器返回了一个html页面,那么这个html页面的内容就是在响应正文当中的。
5.HTTP请求方法
其中最常用的就是GET方法和POST方法。
GET方法一般用于获取某种资源信息,而POST方法一般用于将数据上传给服务器。但实际我们上传数据时也有可能使用GET方法,比如百度提交数据时实际使用的就是GET方法。
GET方法和POST方法都可以带参:
- GET方法是通过url传参的。
- POST方法是通过正文传参的。
从GET方法和POST方法的传参形式可以看出,POST方法能传递更多的参数,因为url的长度是有限制的,POST方法通过正文传参就可以携带更多的数据。
此外,**使用POST方法传参更加私密,**因为POST方法不会将你的参数回显到url当中,此时也就不会被别人轻易看到。不能说POST方法比GET方法更安全,因为POST方法和GET方法实际都不安全,要做到安全只能通过加密来完成。
GET方法
POST方法
当我们使用GET方法时,我们提交的参数会回显到url当中,因此GET方法一般是处理数据不敏感的。
如果你要传递的数据比较私密的话你一定要用POST方法,倒不是因为POST方法更安全,实际上GET和POST方法传参时都是明文传送,所以都不安全,但是POST方法更私密,因为POST是通过正文传参的,不会将参数立马回显到浏览器的url框当中的,所以相对更私密。
6.HTTP状态码
最常见的状态码,比如200(OK),404(Not Found),403(Forbidden请求权限不够),302(Redirect),504(Bad Gateway)。
Redirection(重定向状态码)
重定向就是通过各种方法将各种网络请求重新定个方向转到其它位置,此时这个服务器相当于提供了一个引路的服务。
重定向又可分为临时重定向和永久重定向,其中状态码301表示的就是永久重定向,而状态码302和307表示的是临时重定向。
临时重定向和永久重定向本质是影响客户端的标签,决定客户端是否需要更新目标地址。如果某个网站是永久重定向,那么第一次访问该网站时由浏览器帮你进行重定向,但后续再访问该网站时就不需要浏览器再进行重定向了,此时你访问的直接就是重定向后的网站。而如果某个网站是临时重定向,那么每次访问该网站时如果需要进行重定向,都需要浏览器来帮我们完成重定向跳转到目标网站。
进行临时重定向时需要用到Location字段,Location字段是HTTP报头当中的一个属性信息,该字段表明了你所要重定向到的目标网站。
我们这里要演示临时重定向,可以将HTTP响应当中的状态码改为307,然后跟上对应的状态码描述,此外,还需要在HTTP响应报头当中添加Location字段,这个Location后面跟的就是你需要重定向到的网页,比如我们这里将其设置为百度的首页。
7.HTTP常见的Hander
- Content-Type:数据类型(text/html等)。
- Content-Length:正文的长度。
- Host:客户端告知服务器,所请求的资源是在哪个主机的哪个端口上。
- User-Agent:声明用户的操作系统和浏览器的版本信息。
- Referer:当前页面是哪个页面跳转过来的。
- Location:搭配3XX状态码使用,告诉客户端接下来要去哪里访问。
- Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。
Host
Host字段表明了客户端要访问的服务的IP和端口,比如当浏览器访问我们的服务器时,浏览器发来的HTTP请求当中的Host字段填的就是我们的IP和端口。但客户端不就是要访问服务器吗?为什么客户端还要告诉服务器它要访问的服务对应的IP和端口?
因为有些服务器实际提供的是一种代理服务,也就是代替客户端向其他服务器发起请求,然后将请求得到的结果再返回给客户端。在这种情况下客户端就必须告诉代理服务器它要访问的服务对应的IP和端口,此时Host提供的信息就有效了。
User-Agent
User-Agent代表的是客户端对应的操作系统和浏览器的版本信息。
比如当我们用电脑下载某些软件时,它会自动向我们展示与我们操作系统相匹配的版本,这实际就是因为我们在向目标网站发起请求的时候,User-Agent字段当中包含了我们的主机信息,此时该网站就会向你推送相匹配的软件版本。
Referer
Referer代表的是你当前是从哪一个页面跳转过来的。Referer记录上一个页面的好处一方面是方便回退,另一方面可以知道我们当前页面与上一个页面之间的相关性。
Keep-alive(长连接)
HTTP/1.0是通过request&response的方式来进行请求和响应的,HTTP/1.0常见的工作方式就是客户端和服务器先建立链接,然后客户端发起请求给服务器,服务器再对该请求进行响应,然后立马端口连接。
但如果一个连接建立后客户端和服务器只进行一次交互,就将连接关闭,就太浪费资源了,因此现在主流的HTTP/1.1是支持长连接的。所谓的长连接就是建立连接后,客户端可以不断的向服务器一次写入多个HTTP请求,而服务器在上层依次读取这些请求就行了,此时一条连接就可以传送大量的请求和响应,这就是长连接。
如果HTTP请求或响应报头当中的Connect字段对应的值是Keep-Alive,就代表支持长连接。article/details/132166388
8.Cookie和Session
HTTP实际上是一种无状态协议,HTTP的每次请求/响应之间是没有任何关系的,但你在使用浏览器的时候发现并不是这样的。
比如当你登录一次CSDN后,就算你把CSDN网站关了甚至是重启电脑,当你再次打开CSDN网站时,CSDN并没有要求你再次输入账号和密码,这实际上是通过cookie技术实现的,点击浏览器当中锁的标志就可以看到对应网站的各种cookie数据。
这些cookie数据实际都是对应的服务器方写的,如果你将对应的某些cookie删除,那么此时可能就需要你重新进行登录认证了,因为你删除的可能正好就是你登录时所设置的cookie信息。
Cookie
因为HTTP是一种无状态协议,如果没有cookie的存在,那么每当我们要进行页面请求时都需要重新输入账号和密码进行认证,这样太麻烦了。
比如你是某个视频网站的VIP,这个网站里面的VIP视频有成百上千个,你每次点击一个视频都要重新进行VIP身份认证。而HTTP不支持记录用户状态,那么我们就需要有一种独立技术来帮我们支持,这种技术目前现在已经内置到HTTP协议当中了,叫做cookie。
当我们第一次登录某个网站时,需要输入我们的账号和密码进行身份认证,此时如果服务器经过数据比对后判定你是一个合法的用户,那么为了让你后续在进行某些网页请求时不用重新输入账号和密码,此时服务器就会进行Set-Cookie的设置。(Set-Cookie也是HTTP报头当中的一种属性信息)
当认证通过并在服务端进行Set-Cookie设置后,服务器在对浏览器进行HTTP响应时就会将这个Set-Cookie响应给浏览器。而浏览器收到响应后会自动提取出Set-Cookie的值,将其保存在浏览器的cookie文件当中,此时就相当于我的账号和密码信息保存在本地浏览器的cookie文件当中。
从第一次登录认证之后,浏览器再向该网站发起的HTTP请求当中就会自动包含一个cookie字段,其中携带的就是我第一次的认证信息,此后对端服务器需要对你进行认证时就会直接提取出HTTP请求当中的cookie字段,而不会重新让你输入账号和密码了。
也就是在第一次认证登录后,后续所有的认证都变成了自动认证,这就叫做cookie技术。
Cookie被盗
如果你浏览器当中保存的cookie信息被非法用户盗取了,那么此时这个非法用户就可以用你的cookie信息,以你的身份去访问你曾经访问过的网站,我们将这种现象称为cookie被盗取了。
比如你不小心点了某个链接,这个链接可能就是一个下载程序,当你点击之后它就会通过某种方式把程序下载到你本地,并且自动执行该程序,该程序会扫描你的浏览器当中的cookie目录,把所有的cookie信息通过网络的方式传送给恶意方,当恶意方拿到你的cookie信息后就可以拷贝到它的浏览器对应的cookie目录当中,然后以你的身份访问你曾经访问过的网站。
Session
单纯的使用cookie是非常不安全的,因为此时cookie文件当中就保存的是你的私密信息,一旦cookie文件泄漏你的隐私信息也就泄漏。
所以当前主流的服务器还引入了SessionID这样的概念,当我们第一次登录某个网站输入账号和密码后,服务器认证成功后还会服务端生成一个对应的SessionID,这个SessionID与用户信息是不相关的。系统会将所有登录用户的SessionID值统一维护起来。
此时当认证通过后服务端在对浏览器进行HTTP响应时,就会将这个生成的SessionID值响应给浏览器。浏览器收到响应后会自动提取出SessionID的值,将其保存在浏览器的cookie文件当中。后续访问该服务器时,对应的HTTP请求当中就会自动携带上这个SessionID。
而服务器识别到HTTP请求当中包含了SessionID,就会提取出这个SessionID,然后再到对应的集合当中进行对比,对比成功就说明这个用户是曾经登录过的,此时也就自动就认证成功了,然后就会正常处理你发来的请求,这就是我们当前主流的工作方式。
引入SessionID之后,浏览器当中的cookie文件保存的是SessionID,此时这个cookie文件同样可能被盗取。此时用户的账号和密码虽然不会泄漏了,但用户对应的SessionID是会泄漏的,非法用户仍然可以盗取我的SessionID去访问我曾经访问过的服务器,相当于还是存在刚才的问题。
- 之前的工作方式就相当于把账号和密码信息在浏览器当中再保存一份,每次请求时都自动将账号和密码的信息携带上,但是账号和密码一直在网当中发送太不安全了。
因此现在的工作方式是,服务器只有在第一次认证的时候需要在网络中传输账号和密码,此后在网络上发送的都是SessionID。 - 这种方法虽然没有真正解决安全问题,但这种方法是相对安全的。互联网上是不存在绝对安全这样的概念的,任何安全都是相对的,就算你将发送到网络当中的信息进行加密,也有可能被别人破解。
不过在安全领域有一个准则:如果破解某个信息的成本已经远远大于破解之后获得的收益(说明做这个事是赔本的),那么就可以说这个信息是安全的。
当我们简单构建一个服务器,使用session时