一、TCP
传输控制协议,Transmission Control Protocol 。
面向广域网的通信协议,跨域多个网络通信时,为两个通信端点之间提供一条具有如下特点的通信方式:
基于流、面向连接、可靠通信方式、网络状况不佳时尽量降低系统由于重传带来的带宽开销、不考虑中间网段和节点。
三次握手 : 建立连接
1)客户端发送SYN(SEQ=x)报文给服务端,进入SYN_SENT状态。
2)服务端收到SYN,回应一个SYN(SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态;
3)客户端收到服务端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态;
SYN :同步序列编号(Synchronize Sequence Numbers),TCP/IP建立连接时使用的握手信号。
ACK:确认字符(Acknowlegement character),接收端发给发送端的一种传输类控制字符。
四次挥手 :终止连接
1)某个应用进程首先调用Close,称该端执行"主动关闭"。该端TCP发送一个FIN分节,表示数据发送完毕。
2)接收到这个FIN的对端执行"被动关闭",这个FIN由TCP确认。
3)一段时间后,接收到文件结束符的应用进程将调用Close关闭它的套接字。它的TCP也发送一个FIN。/
4)接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。
通常由客户端执行主动关闭,但是某些协议例如HTTP/1.0由服务端执行主动关闭。
协议规定:
1)数据分片:发送端对数据进行分片,接收端进行重组,由TCP确定分片大小并控制分片和重组;
2)到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认;
3)超时重发:发送发在发送分片时启动超时定时器,如果在定时器超时之后没有收到相应的确认,重发分片;
4)滑动窗口:TCP连接每一方的接收缓冲空间大小都固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出;
5)失序处理:作为IP数据报来传输的TCP分片到达时可能会失序,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层;
6)重复处理:作为IP数据报来传输的TCP分片会发生重复,TCP的接收端必须丢弃重复的数据;
7)数据校验:TCP将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到分片的检验和有差错,TCP将丢弃这个分片,并不确认收到此报文段,导致对端超时并重发。
在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP。
粘包/半包问题
发送端连续给对端发送两个及以上的数据包,对端在一次收取中可能收到的数据包大于1个,可能是几个包加上某个包的部分,或者就是几个完整的包在一起,这个叫粘包。
当然,也可能收取到的只是一个包的一部分,这个叫半包。
如何解决?
1)固定包长的数据包 。比如规定每个协议包大小为64字节,每次收满64字节就取出解析,如果不够,就先存起来。这种格式简单但灵活性差。如果包内容不足指定字节数,剩余空间需要填充特殊信息,如\0;包内容超过指定字节数,又得分包分片,需要额外处理逻辑。
2)以指定字符(串)为包的结束标志。 这种协议包较常见,即字节流中遇到特殊符号值时就认为到了一个包的末尾。例如:FTP协议、发邮件的SMTP协议,一个命令或者一段数据后加上"\r\n"(即CRLF)表示一个包的结束。不足之处是如果协议数据包内容部分需要使用包结束标志字符,就需要对这些字符做转码或者转义操作,避免误解析。
3)包头+包体格式。 包头是固定大小的,且包头中必须含有一个字段来说明包体大小。如果是bodySize,对端先收取包头大小字节,如果不够先缓存直到收够为止,然后解析包头中的bodySize字段,根据包体大小来收取包体大小字节;如果是packageSize,则表示整包大小,需要用packageSize减去包头大小,就能算出包体的大小。
解包处理
二、UDP
用户数据报协议,User Datagram Protocol 。
一种无需建立连接就可以发送封装的IP数据报的方法。
丢包问题 不考虑IP层分片丢失,CRC校验包不完整
1)接收端处理时间过长 调用recv方法接收到数据后,处理数据花了一些时间,处理完后再次调用recv,在这两次调用间隔里,发过来的包可能丢失。修改接收端,将包接收后存入一个缓冲区,然后迅速返回继续recv。
2)ARP缓存过期 ARP缓存时间约10分钟,如果缓存列表没有对方MAC地址或缓存过期,会发送请求获取MAC地址,未获取地址之前,用户发送的数据包会被内核缓存到arp_queue这个队列,默认最多缓存3个包,多余的数据包会被丢弃。
3)缓冲区过小或文件过大 如果报文很大,而缓冲区过小,则无法容纳该报文,那么报文就会丢失。增大缓冲区。
4)缓冲区满 如果socket缓冲区满了,应用未及时处理缓冲区中的包,那么后续的包会被内核丢弃,造成丢包。通过增大缓冲区来缓解丢包,但是如果服务已经过载,简单增大缓冲去并不能解决问题,反而会造成请求全部超时,服务不可用。
5)发送的包巨大 即使send方法会做大包切割成小包发送,但是包太大也不行。巨大的包需要切割为小包再逐个send。
6)发包频率太快 连续发包不sleep。虽然有时可以通过设置接收缓冲解决,但是最好还是sleep一下。
7)局域网内不丢包,公网丢包 切割小包并sleep发送,如果流量过大可能也不灵。
支持一对一、一对多、多对一、多对多交互通信。
包无序问题 在应用层实现如下功能:
1)发送:包的分片、包的确认、包的重发;
2)接收:包的调序、包的序号确认;
利用UDP实现了可靠数据传输的开源:
1)RUDP :可靠用户数据报协议,reliable UDP。提供一组数据服务质量增强机制,如拥塞控制的改进、重发机制及淡化服务器算法等,在不干扰协议的实时特性的同时,允许TCP方式下的流控制行为。
2)RTP :实时传输协议,Real-time Transport Protocol。为数据提供了具有实时特性的端对端传送服务,如在组播或单播网络服务下的交互式视频音频或模拟数据。如果底层网络提供组播方式,RTP可以使用该组播表传输数据到多个目的地。
3)UDT 基于UDP的数据传输协议,UDP-based Data Transfer Protocol。一种互联网数据传输协议,主要目的是支持高速广域网上的海量数据传输,而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。UDT引入新的拥塞控制和数据可靠性控制机制,是面向连接的双向的应用层协议,同时支持可靠的数据流传输和部分可靠的数据报传输。也可以应用在点到点技术(P2P)、防火墙穿透、多媒体数据传输等等。
三、KCP
官方仓库
快速可靠协议,A Fast and Reliable ARQ Protocol
比TCP浪费10%-20%带宽的代价,换取平均延迟降低30%-40%,且最大延迟降低3倍的传输效果。纯算法实现,不负责底层协议的收发,需要使用者自己定义下层数据包的发送方式,以callback方式提供给KCP,连时钟都需要外部传递进来,内部不会有任何一次系统调用。
TCP是为流量设计(每秒内可以传输多少KB数据),KCP为流速设计(单个数据包从一端发送到一端需要多少时间)。
TCP | KCP | 对比 |
---|---|---|
RTO翻倍 | 不翻倍 | 提高传输速度 |
全部重传 | 选择性重传 | 只重传真正丢失的数据包 |
- | 快速重传 | 不用等超时,直接重传 |
延迟ACK | 非延迟ACK | 可调节是否延迟发送 |
UNA | ACK+UNA | - |
- | 非退让流控 | 开着BT都能流畅传输 |
两种ARQ响应模型:UNA(此编号前所有包已收到);ACK(该编号包已收到)。
四、HTTP
超文本传输协议,Hypertext Transfer Protocol
简单的请求-响应协议,运行在TCP之上,指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出,而消息内容则具有类似MIME的格式。每个请求和响应都是独立的,服务器不会主动推送消息给客户端。
HTTP基于B/S架构进行通信,其服务器实现程序有httpd、nginx等,客户端实现程序主要是web浏览器,客户端命令行工具有elink、curl等。
请求报文格式:
请求行 - 通用信息头 - 请求头 - 实体头 - 报文主体
应答报文格式:
状态行 - 通用信息头 - 响应头 - 实体头 - 报文主体
五、WebSocket
在单个TCP连接上进行全双工通信的协议,允许服务器主动向客户端推送数据。
WebSocket通过HTTP/1.1协议的101状态码握手,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
特性:
1)较少的控制开销 相对于HTTP请求每次都要携带完整的头部信息,此项开销显著减少
2)更强的实时性 相对于HTTP请求需要客户端发起服务器才能响应,延迟明显更少
3)保持连接状态 需要先创建连接,使其成为一种有状态的协议,之后通信可以省略部分状态信息,而HTTP请求可能需要每次都携带状态信息,如:身份认证
4)更好的二进制支持 定义了二进制帧,更轻松处理二进制内容
5)可以支持扩展 用户可以扩展协议,实现部分自定义的子协议,如:部分浏览器支持压缩等
6)更好的压缩效果 相对HTTP压缩,WebSocket在适当扩展支持下,可以沿用之前内容的上下文,传递类似数据时,显著提高压缩率
六、RPC
远程过程调用,Remote Procedure Call
进程间通信(IPC)是在多任务操作系统或联网的计算机之间运行的程序和进程所用的通信技术,有两种类型的进程间通信:
1)LPC(本地过程调用)
2)RPC(远程过程调用)
通过IPC和RPC,程序能利用其他程序或计算机处理的进程。客户机执行自己的任务,但靠服务器提供后端文件服务。RPC为客户机提供向后端服务器申请服务的通信机制。
RPC应用场景:
1)分布式操作系统的进程间通讯
2)构造分布式计算的软件环境
3)远程数据库服务
4)分布式应用程序设计
5)分布式程序的调试