我们所写的网络程序,都是在应用层。HTTP协议就是大佬写的应用层协议之一。
序列化和反序列化
协议是一种“约定”,socket,api等接口都是按“字符串”来接发数据的,如果需要传输“结构化的数据”,此时就有了序列化和反序列化。
本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。
序列化的目的:
- 以某种存储形式使自定义对象持久化
- 将对象从一个地方传递到另一个地方
- 使程序更具维护性
认识URL
URL是统一资源定位符。平时我们俗称的“网址”其实就是URL。
- 资源就是我们我们要请求的在服务器上的资源,
- 我们请求哪里的资源?所以先要定位,
- 域名其实就是IP,为了方便阅读
- 服务器都必须有端口号
urlencode和urldecode
对url中的汉子和特殊字符,进行urlencode操作,因为在标准的url规范中,中文和很多的字符是不允许出现在url中的。
服务器获取数据之后进行解码,解码方式与编码方式相反,就是urldecode。
转义规则:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY
格式
HTTP协议格式
HTTP请求
HTTP请求可以分为4个部分,但是并不是所有的HTTP请求都包含了这4个部分
- 第一行:请求行(首行),以空格为单位,请求方法 请求URL HTTP协议的版本
- 第二行到空行之前:请求报头(Header),以行为单位陈列,key:value
- 空行
- 请求正文(Body)
HTTP方法:
HTTP首行中第一个字段就是请求方法。
- GET:获取资源,从服务器上拿下来一部分数据;通过URL传参,有上限,可以传少量,适量的数据。常用
- POST:传输实体主体,上传一些数据;通过正文传参,可以传更多的数据。常用
- PUT:传输文件;
- HEAD:获取报文首部;
- DELETE:删除文件;
- OPTIONS:询问支持的方法;1.1
- TEACE:追踪路径;1.1
- CONNECT:要求用隧道协议连接代理;1.1
- LINK:建立和资源之间的联系;1.0
- UNLINK:断开连接关系。1.0
GET方法和POST方法的区别
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
- GET和POST是HTTP协议中的两种发送请求的方法。GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 (大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。
- HTTP对GET和POST参数的传送渠道(url还是requrest body)提出了要求。GET参数在URL中,但是也可以偷偷的在正文中藏一些数据,至于服务器接不接收这些数据是服务器的实现,POST同样如此,它也可以在URL中传递一些参数。
- GET产生一个TCP数据包,POST产生两个TCP数据报。GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。并不是所有的POST请求都发送两个包,FireFox的POST只发送一个包。网络环境好的情况下,二者的时间差别基本可以无视。在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
HTTP常见报头:
- Host:请求目标主机,客户端告诉服务器,所请求的资源在哪个机子的哪个端口上;
- Connection:浏览器是否支持长连接,keep-alive表示支持长连接,close表示不支持长连接;
- Content-Length:正文长度
- Content-Type:请求(或响应)时给服务器(客户端)传的什么有效载荷类型(数据类型);
- Usr-Agent:声明用户的操作系统和浏览器的版本信息;
- Cookie:用于在客户端存储少量信息,通常用于实现会话(session)的功能。
-
记录第一次输入的用户密码等一些数据把账号密码信息带到报头里。当浏览器发起一些请求时,自动带上Cookie文件(账号密码信息在用户端)。Cookie文件缺点:安全性,结决办法:sessionID:Cookie文件保存在服务器,给用户返回sessionID(唯一的,有时效性)。
- referer:当前页面是从哪个页面跳转过来的
- location:搭配3xx状态码使用,告诉客户端接下来要去哪里访问;
空行
空行之前是报头,空行之后是正文。
正文
正文可以是空字符串,如果正文存在,那么在请求报头中会有一个Content-Length属性来标识正文的长度。
HTTP响应
HTTP响应与请求的格式基本一致
- 第一行:状态行(首行)【版本号】+【状态码】+【状态码解释】
- 第二行到空行之前:响应报头(Header),遇到空行表示响应报头结束
- 空行
- 响应正文(网页)Body:空行之后,允许为空字符串,如果有数据,那么在响应报头会有一个Content-Length属性来标识正文的长度。如果服务器返回一个html页面,那么html页面内容就是在正文中。html告诉你是什么,根据css文件来决定图片咋放,动态效果是gs产生的
HTTP的状态码
HTTP状态码是服务器返回给客户端的。
类别 | 原因短语 | |
1xx | 信息状态码 | 接收的请求正在处理 |
2xx | 成功状态码 | 请求正常处理完毕 |
3xx | 重定向状态码 | 需要进行附加操作以完成请求 |
4xx | 客户端错误状态码 | 服务器无法处理请求 |
5xx | 吴福气错误状态码 | 服务器处理请求出错 |
常见状态码:200(OK),404(Not Found),302(Redirect,重定向),504(Bad Gateway)
302,307临时重定向,每次都要跳转
301永久重定向,以后都不要跳转
长连接和短连接
HTTP协议和TCP/IP协议的关系
HTTP是建立在TCP上的超文本传输协议。HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用IP协议。IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠地传递数据包。HTTP的长连接和短连接本质上是TCP长连接和短连接。
短连接
申请资源时,每次申请一次就连接一次,低效;客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。
短连接优点:节省资源,管理比较简单,存在的连接都是有用的连接,不需要额外的控制手段。
短连接缺点:TCP的建立和关闭操作上浪费时间和带宽。
短连接适用场景:并发量大,但每个用户无需频繁操作的情况下,例如WEB网站的http服务器。
长连接
连接一次就完成所有资源申请;客户端与服务器完成一次请求后,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。
长连接优点:省去较多的TCP建立和关闭的操作,减少浪费,节约时间。
长连接缺点:保活功能的探测周期太长,可以通过修改参数来完善这一缺点。连接一直不关闭,随着客户端连接越来越多,服务器早晚会奔溃,可以设置每个客户端的最大长连接数。长连接一条连接有多个请求,可能会有黏包问题?空行和Content-Length决定了一个长连接该读多少,解决了黏包问题。
长连接的适用场景:操作平凡,点对点的通讯,而且连接数不能太多的情况,例如数据库的连接。
TCP保活功能
客户端消失而连接未断开,会使服务器上保留一个半开放的连接,一直在等待等待客户端的数据。保活功能就是试图在服务器端检测到这种半开放的连接。保活定时器。
1.0版本默认短连接,1.1版本默认长连接。
长连接和短连接的操作过程
短: 建立连接——数据传输——关闭连接......建立连接——数据传输——关闭连接
长:建立连接——数据传输....(保持连接)....数据传输——关闭连接
短连接谁先断开链接总结:(不考虑keepalive)
http1.0
- 带content-length,body长度可知,客户端在接收body时,就可以依据这个长度来接受数据。接受完毕后,就表示这个请求完毕了。客户端主动调用close进入四次挥手。
- 不带content-length ,body长度不可知,客户端一直接受数据,直到服务端主动断开
http1.1
- 带content-length , body长度可知 , 客户端主动断开
- 带Transfer-encoding:chunked body会被分成多个块,每块的开始会标识出当前块的长度,body就不需要通过content-length来指定了。但依然可以知道body的长度 客户端主动断开
- 不带Transfer-encoding:chunked且不带content-length 客户端接收数据,直到服务端主动断开连接。
即 :如果能够有办法知道服务器传来的长度,都是客户端首先断开。如果不知道就一直接收数据,直到服务端断开。
端口号
在TCP/IP协议中,“源IP,源端口号,目的IP,目的端口号,协议号”,这样一个五元组织来标识一个通信。
0 - 1023:知名端口号,HTTP,FTP,SSH等广为使用的应用层协议,他们的端口号是固定的
- ssh服务器:22
- ftp服务器:21
- telnet服务器:23
- http服务器:80
- https服务器:443
1024 - 65335:操作系统动态分配的端口号. 客户端程序的端口号, 就是由操作系统从这个范围分配的.。
查看知名端口号:cat /etc/services
一个进程能bind多个端口号,一个端口号只能被一个进程bind。
UDP协议
UDP协议段格式
- 16位UDP长度,表示整个数据报UDP(UDP首部+UDP数据)的最大长度,最大长度64k(如果超过64k,则需要手动分包,64k是个很小的数字);UDP长度-报文长度=有效载荷长度
- 如果校验和出错,就会直接丢弃。
基于UDP的应用层协议
- NFS: 网络文件系统;
- TFTP: 简单文件传输协议;
- DHCP: 动态主机配置协议;
- BOOTP: 启动协议(用于无盘设备启动) ;
- DNS: 域名解析协议
UDP特点
- 无连接,知道对端的IP和端口号就直接传输,不建立连接;
- 不可靠,没有确认机制,没有重传机制,如果出错了也不会给应用层返回任何错误信息;
- 面向数据报,来多少发多少,不拆分,不合并,报文与报文之间界限明确,每个包独立成文。不能灵活的控制读写数据的次数和数量。
- UDP没有真正意义上的发送缓冲区,sendto会直接把报文交给内核,内核传给网络层协议。。
- UDP有接收缓冲区,不能保证接收到的UDP顺序和发送的UDP顺序一致,如果这个缓冲区满了,后续到达的数据就会被丢弃。
- UDP的socket既能读,又能写,双全工。
UDP实现可靠传输
传输层无法保证数据的可靠传输,可以通过应用层来实现。实现确认机制、重传机制、窗口确认机制。
- 发送:包的分片、包确认、包的重发
- 接收:包的调序、包的序号确认
目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。
- RUDP:如拥塞控制的改进、重发机制及淡化服务器算法等
- RTP:提供了具有实时特征的端对端传送服务
TCP协议
TCP协议全程为“传输控制协议”,对数据的传输要进行详细的控制。
TCP协议段格式
源/目标端口号
表示数据从哪个进程来,到哪个进程去。
32位序列号:
TCP是面向字节流的,在一个TCP连接中传输的每一个字节都按照顺序编号。
序号字段值:本报文段所发送的数据的第一个字节的序号。
一共2^32个序号,每2^32个字节,出现序列号环绕,再从0开始。旧序号的数据早已经到达网络终点或者丢失了。
32位确认号:
期望收到对方下一个报文段的序号值。
通讯的任何一方在收到一个报文之后,都要发送一个相对应的【确认报文】来表达确认收到,确认报文就会包含确认号
100kb的html文档被分成4等分:
报文顺序 | 序号值 | 确认号 |
0-25599 | 0 | 25600 |
25600-51199 | 25600 | 51200 |
4位 TCP首部长度:
由于TCP首部包含一个长度可变的选项部分,就需要一个值来指定这个TCP头部到底有多长,有多少位32bit(有多少个字节)TCP头部最大长度是15*4 = 60
6位保留 Reserved
保留至今后使用,目前置0.
6位标志位:
- URG: 紧急指针是否有效,表示本报文段中发送的数据是否包含紧急数据,与后面的紧急指针字段搭配使用;
- ACK: 确认号是否有效,ACK=1时,前面的确认号字段才有效。TCP规定,连接建立后,ACK必须为1;
- PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走 ,而不是缓存起来;
- RST: 对方要求重新建立连接,释放连接,然后再重新建立连接; 我们把携带RST标识的称为复位报文段 ;
- SYN: 请求建立连接; 用来同步序号,我们把携带SYN标识的称为同步报文段;SYN=1,ACK=0时,是请求建立连接的报文、SYN=1,ACK=1,表示对方同意建立连接、只有在前两次握手中SYN才设置为1。
- FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段
16位窗口大小
流量控制,填自己接收缓冲区剩余空间的大小。
16位校验和
提供额外的可靠性
16位紧急指针
标记紧急数据字段中的位置
10*32位选项部分:
- MSS最大报文段长度:指明数据段的最大长度,通信双方可以有不同的MSS值,默认536字节。MSS值出现在SYN报文中。
- 窗口扩大选项:窗口大小字段有16位,可以扩大窗口来满足性能和吞吐率。
- SACK选择确认项:确保只重传缺少的报文段,而不是重传所有报文。需要两个功能字节,一个表示是否使用SACK选项,另一个指明这个选项占用多少字节。描述丢失的报文段。最多描述4个丢失的报文段。
- 时间戳选项:可以用来计算RTT(往返时间),发送方把当前的时间放入时间戳,接收方收到这个报文时,把这个时间戳字段的值复制到确认报文中,当发送方收到确认报文后就可以计算出RTT。可以用来防止回绕序号,也可以用来区分相同序列号的不同报文
- NOP:它要求所有选项部分中的每种选项长度都是4字节的倍数,不足的用NOP填充。也可以用来分隔不同的选项字段,扩大窗口选项和SACK之间用NOP隔开。
TCP协议特点:
- 有连接,面向连接的
- 可靠,有确认应答机制,有重传机制
- 有发送/接收缓冲区
- 保证接收报文的顺序
参考博文:
TCP保活功能时间修改:http://blog.sina.com.cn/s/blog_62a85b950102vrr4.html
长连接和短连接:https://www.cnblogs.com/gotodsp/p/6366163.html
一次HTTP请求,谁先断开:https://www.cnblogs.com/web21/p/6397525.html
TCP首部格式:https://www.cnblogs.com/fantastic123/p/8968132.html
TCP和UDP区别,其优缺点:https://www.cnblogs.com/xiaomayizoe/p/5258754.html