TCP / IP 不仅仅是指TCP和IP这两种协议,而是一系列网络协议的总和, 而这些协议中最核心的2个协议就是TCP和IP,所以被称为TCP/IP网络协议族。 TCP/IP协议族是互联网的基础通信架构。
HTTP超文本传输协议。
是用于Web浏览器和Web服务器之间传递数据的协议。 HTTP协议以明文的方式发送内容,不提供任何方式的数据加密, 因此HTTP是一种不太安全的协议。
HTTPS协议在HTTP协议的基础上加入了SSL协议, SSL依靠证书来验证服务器的身份, 所以HTTPS协议叫HTTP协议来说是安全的。 SSL协议作用于传输层协议和各种应用层协议之间。
SMTP简单邮件传输协议。
它是用于从源地址到目标地址传输邮件的协议(发送邮件)
POP邮局协议的第3个版本。
POP3协议允许电子邮件客户端下载服务器上的邮件, 但是在客户端上的操作,并不会反馈到服务器上。 也就是说客户端的操作对服务端没有影响。(接受并处理邮件)
IMAP交互式邮件存取协议。
它和POP3协议类似 ,但是IMAP对客户端的操作会反馈到服务端, 也就是说客户端邮件的状态与服务端邮件的状态是一致的。(接受并处理邮件)
DNS域名系统。
DNS服务器可以看做是一个域名与IP地址相互映射的分布式数据库。 我们使用浏览器访问google的时候需要输入:google.com, 浏览器会帮我们到DNS服务器查询google.com对应的IP地址, 从而能够访问google的服务器。
FTP文件传输协议。
FTP协议用于从一台主机将文件传输到另一台主机上。 但FTP协议在文件传输过程中,并没有为文件提供加密措施, 所以FTP协议是不安全的。
SFTP安全文件传输协议。
SFTP实际可以看做是SSH的一部分。 当使用SFTP登录到目标主机后,可以使用SFTP指定的命令进行数据传输, 并且传输的数据是加密过的。
Telnet和SSH都可以作为远程登录的协议。 但Telnet使用的是明文来传输数据,并且没有提供数据加密措施, 是不安全的协议。 而SSH协议则提供了对数据的压缩和加密,比Telnet要安全的多。 所以现在几乎大部分场景都使用的是SSH作为安全数据传输和远程登录的协议, 并且SSH提供了对SFTP的支持。
TCP传输控制协议。
TCP协议是一种面向连接的,可靠的,基于字节流的传输协议。 TCP协议适用于对数据准确性和可靠性要求较高的应用,如文件传输等。
TCP会采用校验和,确认应答与序列号, 拥塞控制,流量控制,超时重传, 连接管理(三次握手,四次回收)等机制保证传输的可靠性。
TCP报文格式:
UDP用户数据报协议。
与TCP协议不同,UDP协议并不保证数据传输的可靠性, 无论目标主机是否可通信,UDP都会发送数据。
UDP适用于传输效率要求较高,允许一定数据丢失的应用,如语音,视频等。
PS:UDP报文格式
在数据传输过程中,将发送的数据段分成若干个16位的整数。 将这些整数加起来,并且前面的进位不能丢弃,补在后面,最后取反, 得到校验和。
发送方在发送数据之前计算校验和,并将校验和填充到TCP报文中, 而接收方收到数据后,对数据以同样的方式进行计算,求出校验和, 与发送方的进行比对。如果比较失败,接收方将丢弃数据包。
在TCP传输过程中,每次接收方收到数据后,都会对发送方进行应答, 也就是响应ACK报文,这个报文中有对应的确认序列号。
在TCP传输时,由于确认应答和序号机制,当发送方发送完数据后, 会等待接收方的ACK报文,并解析判断ACK报文(一般来说ACK为seq+1), 如果发送方一直没有等到接收方的ACK报文,那么将重新发送一遍数据。
连接管理是TCP数据传输前和连接断开时的工作, 包括三次握手与四次挥手的过程。
TCP连接发送端和接收端都有一个缓冲区,如果发送端的发送数据过快, 导致接收端来不及处理数据,缓冲区就被填充满了,那么接下来的数据, 接收方就会丢弃数据,导致丢包等连锁反应产生。
TCP根据接收端的处理能力,来决定发送端的发送速度,这个机制就是流量控制。 TCP的报文中,有一个16位的窗口字段, 窗口大小就是接收端计收数据缓冲区的剩余大小,这个数字越大, 代表接收端缓冲区的剩余空间越大。
接收端在发送ACK确认报文时,会将自己当前的窗口大小填入, 这样发送方就会根据ACK报文里的窗口大小的值改变自己的发送速度。 如果接收方窗口大小的值为0,那么发送方将停止发送数据, 并定期的向接收端发送窗口探测数据,让接收端把窗口大小告诉发送端。
滑动窗口是接收端的使用的窗口大小,用来告诉发送端接收端的缓存大小, 从而可以控制发送端的发送速度。 而发送端发送的速度则是使用发送端的窗口来实现的。
发送端的窗口就是拥塞窗口了,发送端的拥塞窗口不代表缓存, 而是指发送端每次最多可以发送的数据包数。
当TCP连接建立时,拥塞窗口被初始化为1,每次发送数据后, 收到一个ACK,拥塞窗口就增加一个报文段, 发送端取拥塞窗口与滑动窗口的最小值作为发送上限,从而实现拥塞控制。
如果网络比较拥堵,那么一次性发送大量数据将,可能产生大量的丢包, 继而发生一系列的连锁反应,如超时重传等。 拥塞控制就避免了一次性发送过多的数据,而导致的问题。
TCP是面向连接的,三次握手是客户端与服务端进行数据传输前的准备工作。 这样做是为了建立可靠的传输信道,尽可能的保证数据的安全。
三次握手是指建立一个TCP连接时需要客户端和服务端总共需要发送3个数据包确认连接的建立。
TCP三次握手的过程:
1.第一次握手
客户端发送一个数据包发送给服务端。 该数据包的标志位SYN=1,表示客户端请求建立连接, 随机产生的序列号seq=J。 客户端进入SYN_SENT状态,等待服务端确认。
2.第二次握手
服务端收到客户端的数据包后,由标志位SYN=1判断客户端需要建立连接。 于是响应一个确认数据包给客户端。 该确认数据包的标志位SYN和标志位ACK都为1,确认序列号ack=J+1, 随机产生的序列号seq=K。服务端进入SYN_RCVD状态。
3.第三次握手
客户端收到服务端的确认数据包后,检查确认序列号ack是否为J+1, 标志位ACK是否为1。 如果正确则将发送最后一个数据包给服务端。 该数据包的标志位ACK为1,确认序列号ack=K+1。 服务端收到后检查确认序列号ack是否为K+1,标志位ACK是否为1。 如果正确,则客户端和服务端都进入ESTABLISHED状态。
三次握手后,客户端和服务端就可以传输数据了。
四次挥手是客户端与服务端关闭连接时的结尾工作。 TCP是全双工的,即:客户端可以通过这条TCP连接向服务端发送数据(上传), 服务端也可以通过这条TCP连接向客户端发送数据(下载)。 因此,客户端和服务端都需要单独的关闭连接。 客户端关闭连接是关客户端到服务端的通信传输, 而服务端关闭连接是关闭服务端到客户端的通信传输, 所以需要四次挥手来保证2端的关闭。
四次挥手是指断开连接时,客户端与服务端总共需要发送4个数据包确认连接的断开。
客户端或服务端任意一方都可以发送断开连接的请求。
TCP四次挥手的过程:
1.第一次挥手(假设客户端请求断开)
客户端发送一个数据包给服务端,用于关闭Client到Server的数据传输。 数据包的标志位FIN=1,随机产生的序号seq=M,客户端进入FIN_WAIT_1状态。
2.第二次挥手
服务端收到客户端的断开请求后,将发送一个数据包响应给客户端。 该数据包的标志位ACK=1,确认序列号ack=M+1。 客户端收到后进入FIN_WAIT_2状态,服务端进入CLOSE_WAIT状态。
3.第三次挥手
服务端发送一个数据包给客户端,用于关闭服务端到客户端的数据传输。 数据包的标志位FIN=1,随机产生的序列号seq=N。 服务端进入LAST_ACK状态。
4.第四次挥手
客户端收到服务端的断开请求后,就可以关闭连接了。 于是发送最后一个数据包结束与服务端的连接,并进入TIME_WAIT状态。 最后一个数据包的标志位ACK=1,确认序列号ack=N+1。 服务端收到最后一个了数据包后,就关闭了连接,状态就为CLOSED, 如果服务端没有收到ACK,客户端可以重传。客户端等了一会儿, 最终没有收到响应,就代表服务端已经关闭连接了,客户端也就会关闭连接。
上面是客户端或服务端中的一段主动关闭,另一段被动关闭, 实际还可能还会出现同时发起关闭的情况:
在TCP传输数据时,客户端发送数据,实际上是把数据写入到了TCP的缓冲区中, 粘包和半包也就可能在此时产生。
假设客户端给服务端发送两条数据: "ABC"和"DEF", 服务端这边的接受可能会有多种情况: 可能是一次性收到了这两条消息:"ABCDEF", 也有可能分批收到了消息:"ABC","DEF"或"AB","CD","EF"。
服务端一次性收到了所有数据包,这种情况就是粘包。
服务端分批收到数据包,这种情况就是半包。
如果客户端发送的包的大小比TCP的缓冲区要小, 并且TCP的缓冲区可以存放多个包,客户端一次性就可能向服务端发送多个包, 这时服务端从TCP缓冲区中就可能读取多个包,这种现象就叫粘包。
如果客户端发送的包的大小比TCP缓冲区要大, 那么这个数据包就可能被分为多个包,就需要多次发送, 而服务端第一次从缓冲区里获取的数据只是整个数据包的一部分,这时候就产生了半包。
粘包的主要原因是: 发送端发送的数据大小 < Socket缓冲区大小, 服务端一次性就读取了Socket缓冲区数据。
半包的主要原因是: 发送端发送的数据大小 > Socket缓冲区大小, 服务端读取数据不够及时,只读取到了数据的一部分。
总结起来就是:多次发送可能共用一个传输,一个发送可能多占用多个传输。
其实归根到底,究其根本原因是:
TCP是面向字节流的协议,消息之间没有边界。 而UDP虽然也可以一次性传输多个包或者多次传输一个包 但UDP的每个消息都是有边界的,因此不会有粘包和半包问题。
固定长度:这种方式是为消息设定一个固定长度。虽然实现简单,但缺点很大,如果消息的大小本身就比较小, 那么这样做就很浪费空间了。
分隔符:这种方式是为消息边界添加分隔符。这样做实现也是比较简单,也不再浪费空间, 不过当内容本身也有分割符时,那就需要转义了,就可能需要对整个内容进行扫描,效率上就比较低。
添加数据的长度字段:这种方式是为报文添加一个Length字段,存储消息的长度。 在Http协议的报文中,有一个字段为Content-Length,专门存储数据的长度,这种方式是比较好的。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。