我们知道网络层(IP),可以实现两个主机之间的通信。但是这并不具体,因为,真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程在交换数据。IP协议虽然能把数据报文送到目的主机,但是并没有交付给主机的具体应用进程。而端到端的通信才应该是应用进程之间的通信。
UDP,在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。虽然UDP不提供可靠交付,但是正是因为这样,省去和很多的开销,使得它的速度比较快,比如一些对实时性要求较高的服务,就常常使用的是UDP。对应的应用层的协议主要有 DNS,TFTP,DHCP,SNMP,NFS 等。
TCP,提供面向连接的服务,在传送数据之前必须先建立连接,数据传送完成后要释放连接。因此TCP是一种可靠的的运输服务,但是正因为这样,不可避免的增加了许多的开销,比如确认,流量控制,拥塞控制等。对应的应用层的协议主要有SMTP,TELNET,HTTP,FTP等。
TCP是面向连接的、可靠的、基于字节流的传输层通信协议,把连接作为最基本的对象,每一条TCP连接都有两个端点,这种断点我们叫作套接字(socket),它的定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。
(1)源端口和目的端口,各占2个字节,分别写入源端口和目的端口;
(2)序列号seq,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始;
(3)确认应答号ack,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号seq字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序列号seq是701,于是B在发送给A的确认报文段中把确认号ack置为701;
(4)数据偏移/首部长度,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远;
(5)保留,占6位,保留今后使用,但目前应都位0;
(6)紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据;
(7)确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
(8)推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1;
(9)复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接;
(10)同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;SYN=1的报文不能携带数据,占1个序号。
(11)终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
(12)窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受;
(13)检验和,占2字节,校验首部和数据这两部分;
(14)紧急指针,占2字节,指出本报文段中的紧急数据的字节数;
(15)选项,长度可变,定义一些其他的可选的参数。
(1)连接管理:TCP是面向连接的,三次握手和四次挥手都保证了本次数据传送的可靠性。
(2)序列号:保证数据段的按序到达,TCP是面向字节流的,它对每一个字节都进行了编号,接收端也是根据序号来对收到的数据进行排序,如果中间有某个数据报丢了,则之后的数据报还是会接受,但是不会对发送端返回之后的确认,而是会重复发送对丢失处之前数据的确认,保证发送端会对丢失数据段进行重发。(3)超时重传机制:当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
(4)流量控制:根据接收端处理数据的能力来控制发送端发送数据的速度。接收端将自己接收缓冲区的空闲空间的大小填充到TCP的报文头部中的窗口大小的字段中,通过ACK确认应答发送给发送端。如果接收端的接收缓冲区快满了,接收端就会将窗口大小设置为一个更小的值发送给发送端,这时发送端的发送速度就会减缓;如果接收端接收缓冲区彻底满了,接收端就会将窗口大小设置为0,这时发送端便停止发送数据段,但是会定时的发送一个窗口探测报文,以此来获取接收端的接收缓冲区状态。
(5)拥塞控制:TCP的拥塞控制由4个核心算法组成“慢启动”(Slow Start)、“拥塞避免”(Congestion voidance)、“快速重传 ”(Fast Retransmit)、“快速恢复”(Fast Recovery)。
首先需要了解一个概念,为了在发送端调节所要发送的数据量,定义了一个“拥塞窗口”(Congestion Window),在发送数据时,将拥塞窗口的大小与接收端ack的窗口大小做比较,取较小者作为发送数据量的上限。拥塞控制主要是四个算法:
1、慢启动:当建立新的TCP连接时,拥塞窗口(congestion window,cwnd)初始化为一个数据包大小。源端按cwnd大小发送数据,每收到一个ACK确认,cwnd就增加一个数据包发送量。
2、拥塞避免:一旦进入到拥塞避免,则说明cwnd目前的值里拥塞可能并不遥远了,你就不应该使用慢启动那种指数增长的方式扩展cwnd,此时用的是较为保守的方式,每个RTT只是将cwnd的值增加1个MSS。
(1)TCP建立连接前,客户端和服务端都是关闭的状态,主动发出连接请求的是客户端,服务端被动的接收请求。
(2)TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
(3)第一次握手(连接请求报文,SYN):TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号seq=x,此时,TCP客户端进程进入了SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
(4)第二次握手(同意建立连接确认报文,SYN+ACK):TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
(5)第三次握手(确认报文,ACK):TCP客户进程收到服务端回复的确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方可以开始通信了。
注:前两次握手不可以携带数据,第三次握手可以携带数据。
(1)避免历史连接,造成资源浪费
如果只建立两次握手连接的机制,假定某一个连接请求因为网络拥塞的原因无法即使发送至服务端,导致客户端无法及时收到确认报文,因此会重新向服务端发送服务器超时重传,若此时客户端与服务端完成握手连接,传输数据并关闭连接,而此前失效的连接请求又到达了服务端,两次握手机制会将客户端与服务端再次建立连接,造成了不必要的资源浪费。但采用三次握手协议,即使失效报文传送过来,服务端接收到报文后回复了确认请求,客户端也不会再次发出确认,无法建立连接。
(2)同步双方初始的序列号
在TCP通信中,通信双方都需要维护一个序列号(字节流中每个字节的序号),序列号是保证可靠传输的关键,它可以是接收方去除重复接收的数据、接收方根据序列号按需接收数据、表示发出的数据包中已经发出的部分。
当客户端发送携带序列号seq的SYN报文,需要服务端回复一个带有应答序列号ack的ACK报文。同样,服务端发送一个带有序列号seq的SYN报文,客户端也会回复一个带有应答序列号ack的ACK报文。从而保证了通信双发序列号的同步性。
(3)4次握手可以简化为3次
4次握手连接同样可以实现一个可靠的连接服务,但是第2步和第3步是可以直接合并成1步的,因此简化为3步即可。
因为网络中的报文会延迟、会复制重发、也有可能丢失,这样会造成的不同连接之间产生互相影响,所以为了避免互相影响,客户端和服务端的初始序列号是随机且不同的。
基于时钟生成随机数
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
我们都知道TCP连接建立是需要三次握手,假设攻击者短时间伪造不同IP地址的SYN 报文,服务端每接收到一个SVN报文,就进入SYN_RCVD状态,但服务端发送出去的ACK + SYN报文,无法得到未知IP主机的ACK应答,久而久之就会占满服务端的SYN接收队列(未连接队列),使得服务器不能为正常用户服务。
(1)数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
(2)第一次挥手:客户端进程发出连接释放FIN报文,并且停止发送数据。释放数据报文首部FIN=1,其序列号seq=u(等于前面已传送过来的数据最后一个字节序号+1),客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据也要消耗一个序号。
(3)第二次挥手:服务器收到连接释放报文回复确认ACK报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时服务端进入CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
(4)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
(5)第三次挥手:服务器处理完数据后,就向客户端发送连接释放FIN报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
(6)第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认ACK报文,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,客户端必须经过2MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
(7)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
MSL为报文最大生存时间,TCP允许不同的实现可以设置不同的MSL值。
(1)保证连接正确关闭:
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。
(2)防止旧连接的数据包
防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。如果不设置2MSL时间,假定连接中有一个数据包被延迟了,而后当前连接断开后这个端口的TCP又被复用了,将导致这个被延迟的数据包被新的连接正确接收,导致数据混乱。如果设置了2MSL机制,客户端发送完最后一个确认报文后,在2MSL时间中可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
(1)TCP:
服务端:
创建socket:socket();
绑定IP地址及port信息到socket:bind();
设计允许最大连接数:listen();
接收客户端的连接:accept();
首发数据:send();recv();或read();write();
客户端:
创建socket:socket();
绑定IP地址及port信息到socket:bind();
连接服务器:connect();
首发数据:send();recv();或read();write();
UDP不提供复杂的传输控制机制,利用IP提供面向无连接的通信服务,UDP的头部非常简单:
(1)源端口、目的端口:告诉udp协议,报文应该发送到哪。
(2)包长度:保留了UDP首部和数据的长度和。
(3)校验和:为了提供可靠的UDP首部和数据设计的。
(1)连接性:TCP是面向连接的传输层协议,进行通信前需要建立连接;UDP不需要先建立连接,直接进行数据传输。
(2)服务对象:TCP是一对一的两点传输服务,UDP支持一对一、一对多、多对多的交互通信。
(3)可靠性:TCP提供可靠的交付通信,数据可以无差错、不丢失、不重复的按需到达;UDP尽最大努力交付,不保证可靠交付。
(4)拥塞控制、流量控制:TCP提供拥塞控制与流量控制,保证数据传输的安全性。UDP没有,即使网络十分堵塞,也不影响发送速率。
(5)首部开销:TCP的首部开销较大,没有使用选型字段时是20个字节;UDP首部开销小,是8个字节。
(6)TCP是基于字节流模式,UDP是面向数据报模式
(1)单播Unicast:是客户端与服务器之间的点到点连接。
(2)广播BroadCast:主机之间“一对所有”的通讯模式,广播者可以向网络中所有主机发送信息。广播禁止在Internet宽带网上传输(广播风暴)。
(3)组播MultiCast:主机之间“一对一组”的通讯模式,也就是加入了同一个组的主机可以接受到此组内的所有数据。
组播报文的目的地址使用D类IP地址,D类地址不能出现在IP报文的源IP地址字段。单播数据传输过程中,一个数据包传输的路径是从源地址路由到目的地址,利用“逐跳”的原理[路由选择]在IP网络中传输。
然而在ip组播环中,数据包的目的地址不是一个,而是一组,形成组地址。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据立即开始向接收者传输,组中的所有成员都能接收到数据包。组播组中的成员是动态的,主机可以在任何时刻加入和离开组播组。
用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某一个多播组的主机也可以向该多播组发送数据包。