计算机网络传输层负责提供不同计算机进程与进程之间的通信,而TCP、UDP协议是位于传输层上的两个协议。
TCP协议:面向连接(传输数据前后需建立和释放连接),可靠(确保对方可以收到数据,若对方未收到数据或报文不完整被接收方丢弃后,会进行重发),时延大,适于大文件传输。
UDP协议:无连接(传输数据不需要建立连接),不可靠(不保证对方可以收到数据,若对方未收到数据或报文不完整被接收方丢弃后,不会重发。使用UDP协议的程序需要靠应用层去提供可靠性的保证),时延小,适用于小文件传输。
通过IP地址,我们可以定位到网络中的一台计算机,而通过端口号,我们可以定位到这台计算机上具体的一个进程。端口号占16个bit,最多可表示65536个端口。(套接字Socket由IP地址和端口号组成,唯一定位了一台计算机上的具体的一个进程)
UDP报文格式:
UDP报文由首部字段和数据字段组成。首部字段长度固定为8个字节,由源端口号(发送该报文的进程端口号,可为空)、目的端口号(指明报文的接收进程的端口号)等部分组成。
TCP报文格式:
UDP报文也分为首部字段和数据字段。首部字段总长度不固定,由一个20字节的固定首部和一个长度可变的选项字段构成。
首部字段中重要的字段:
(TCP协议是面向字节流的:在使用TCP协议发送数据时,TCP协议会对要发送的数据的每个字节编号,并在建立连接后,分多个大小不等的TCP报文,像流一样源源不断的将数据发送给接收方)
-源/目的端口号:发送和接收进程的端口号。
-序号:用于表示该TCP报文的数据字段的第一个字节的编号。在SYN=1和FIN=1时,序号代表的是报文本身的编号。
-确认号:用于告知报文发送方,接收方已经正确收到了该编号之前的所有数据,下份报文请从该编号的数据开始发送。
-ACK标志位(确认位):当该标志位为1时,确认号中的内容才有效。
-SYN标志位(同步位):建立连接时使用。
-FIN标志位(终止位):终止连接时使用。
TCP的发送端和接收端都有各自的缓存区域。发送方的缓存区域用于存储准备发送的数据和已经发送但未收到确认的数据(有可能需要重发);接收方的缓存区域用于存储已经到达但还没来得及被应用程序读取的数据和没按序到达的数据(如123和78号字节先到达了,这时候数据会存在缓存区域中,等待56号数据到达后,才会让应用程序去读取)
(TCP协议是全双工的,双方都可以是发送方或接受方)
TCP实现可靠传输的机制:校验、序号、确认、重传
校验:TCP报文中含有一个校验和,接收方可通过该值来校验数据的完整性和正确性。
序号:发送的数据都会按字节编号,从而能保证接收方接收到的数据的有序性。
确认:每次接收到数据后,在下一次发给发送方的报文中的确认号部分,会对已收到的数据进行确认。
重传:若发送方发送出去报文后,在一定时间内,没收到接收方的回复,则会重传该报文。
·建立TCP连接(三次握手):
(另:TCP协议规定,连接建立后,之后的每个报文的ACK字段都要为1)
三次握手的意义:(i) 确保双方信道的通畅 (ii) 约定序号起始值
其本质应该是四个步骤,但是第二三步可以合并为一个步骤,所以最后只需三步。
第一步:客户端发出报文,约定客户端处的起始编号。
第二步:客户端收到回复。此时客户端处知晓,(i)服务端信道正常 (ii).服务端已知晓客户端约定的起始编号。因此,下一次报文可以向服务端发送要发送的数据了。
第三步:服务端发出报文,约定服务端处的起始编号。
第四步:服务端收到回复。此时服务端处才能知晓,(i)客户端信道正常 (iii).客户端已知晓服务端约定的起始编号。因此,下一次报文可以向客户端发送要发送的数据了。
TCP是全双工协议。前两步是站在客户端的角度,后两步是站在服务端的角度。
上述过程中,第二步服务端发送回复报文和第三步服务端发送约定起始编号的报文,可以合并为一步,即发送回复报文的同时告知起始编号。从而变成了三次握手。
·释放TCP连接(四次挥手):
第一步:客户端处已无数据需要传送,请求断开连接
第二步:服务端回复确认信息,表示收到断开连接的请求。客户端收到该报文后,仅关闭写端,保留读端,可以读取服务端发来的报文和回复确认报文(报文中不能包含数据字段)。
......此间,服务器依旧可以向客户端发送数据......
第三步:服务端处已无数据需要传送,请求断开连接
第四步:客户端回复确认信息,表示收到断开连接的请求。服务端收到该报文后,关闭读写端。客户端回复后,并不会立即关闭读端,而是会等待一段时间。若服务端未收到该回复报文,客户端保留读端的这段时间可以确保能读取到服务端重发的报文,并重发回复,再次等待,直到等待的这段时间内一直未收到报文,则表示服务端已收到回复。此时,客户端关闭读端。
至此,客户端和服务端的读写端都已关闭,四次挥手完成。
(注:第二步后,客户端所有回复的报文的序号和服务端所有发送的报文的确认号都为u+1。这是因为客户端每次回复的报文中都不含有数据字段,服务端并没收到任何新的数据,所以确认号一直都保持为u+1,而客户端也会一直用序号u+1)