TCP与UDP的区别

TCP是面向连接的可靠的字节流服务

UDP是无连接的不可靠的数据报服务

本文主要是从有无连接,可不可靠,服务类型的不同来看TCP与UDP的区别。

TCP字节流服务与UDP数据报服务的区别

TCP字节流服务:

                                   

       字节流传输有自己的缓冲区,发送端发送多次可能都存储在缓冲区,而向接收端发送时可能会把多次发送的数据合并来发送。相对应的,接收端也有自己的接收缓冲区,数据先存储在接收缓冲区,用户可以根据自己的需求来决定一次获取多少数据,可以一次把所有数据都接收到,也可以一点一点的多次获取(如上图,发送端用户发送三次数据,首先存储在发送缓冲区,而真正发送的时候只发送了两个TCP报文段,传输到接收端后,接收端首先将这两个报文段存储到接收缓冲区,然后一次性获取所有数据)。因此,字节流服务发送数据的次数与接收数据的次数没有关系;字节流服务底层数据发送或接收时,数据有可能被分开或合并。

UDP数据报服务:

                                    

    相对于字节流传输,数据报的传输就比较简单,发送端每发送一次就对应一个UDP数据报,数据传输到接收端时,一个UDP数据报接收一次(如上图,用户发送两次,传输层也有两个UDP数据报,相对应的接收端有两个UDP数据报,用户分两次接收)。可以看出:数据报服务发送数据的次数与接收数据的次数相等。除此之外,数据报还有一个重要的特点:如果recvfrom一次未将数据读取完,则UDP报文段中剩余的数据丢失。

数据传输的可靠与不可靠

要谈论数据可靠不可靠首先得明白数据传输满足那些条件才算可靠。一般来说,数据传输可靠要满足以下几个条件:

1.所有数据都能到达对端

2.数据不乱序

3.数据不出错

那么TCP是如何做到这一点的呢?我们来看看TCP的头部

                                         

前20个byte的固定部分(图中前5行)是每个TCP报文段都必须有的,后40个byte选项是可有可无的。所以TCP头部最小20byte,最大60byte。

以下介绍TCP头部包含的内容(我们这里只关注前20个字节的固定部分):

      1> 16位源端口号:告知主机该报文段来自哪个端口。

      2> 16位目的端口号:告知主机传给哪个上层协议或应用程序。

      3> 32位序号:一次TCP通信过程中某一个传输方向上的字节流的每个字节的编号。

                                                       

为了能够更进一步的说明这32位的作用,如上图,假设主机A要给主机B发送120byte的数据,这里是分为四个报文段来传输的,第一个报文段的序号值是系统初始化的某个随机值ISN(这里给的2000),后续的TCP报文段中的序号值将被系统设置为ISN+该报文第一个字节在整个字节流中的偏移(例如:第二个报文段的第一个字节在整个报文的偏移量为30,所以2000+30=2030)。事实上,除了第一个报文段的序号值是系统初始化的某个随机值ISN,后续的报文段的序号值就是ISN+已发送的字节数。

其实,这32位序号来保证数据不乱序。只要按图中1、2、3、4的顺序来接收数据,数据就不会乱序。

      4> 32位确认号:对另一方的TCP报文段的响应。其值是收到的TCP报文段的序号值+1。还是上面的例子,当主机B收到主机A的序列号为2000的报文段后,会给主机A回复2001,表示自己已经收到序列号为2000的报文段。如果在一定的时间内收不到确认消息,发送方会再次发送该消息(超时重传机制)。32位确认号&超时重传机制保证所有数据都到达对方。

      5> 4位头部长度:标识TCP头部有多少个4byte(32bit)。4位最大能表示15,所以TCP头部最长是60byte。

      6> 6位标志位:

  • URG标志:表示紧急指针(urgent  pointer)是否有效。
  • ACK标志:表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。
  • PSH标志:提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间。
  • RST标志:表示要求对方重新建立连接。我们称携带RST标志的TCP报文段为复位报文段。
  • SYN标志:表示请求建立一个连接。我们称携带SYN标志的TCP报文段为同步报文段。
  • FIN标志:表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段为结束报文段。

      7> 16位窗口大小(window  size):TCP流量控制的一个手段。这里的窗口,是接收通告窗口(Receiver Window,RWND)。它负责告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,对方根据缓冲区剩余大小控制发送数据的速度。

      8> 16位校验和(TCP  checksum):由发送端填充,接收端对TCP报文段执行CRC算法以检验TCP报文段在传输过程中是否损坏。这里的校验不仅包括TCP头部,也包括数据部分。这就保证了数据不出错

      9> 16位紧急指针(urgent  pointer):是一个正的偏移量。它和序号字段的值相加表示最后一个紧急数据的下一字节的序号。也就是说,这个字段是紧急指针相对当前序号的偏移。TCP紧急指针是发送端向接收端发送紧急数据的方法。

TCP字节流服务之所以可靠,主要是靠TCP头部的这些控制信息。

接下来我们来看看UDP的头部

                                                           

我们可以看到,相对于TCP的头部,UDP的头部简单多了。UDP的头部只占8个字节,前四部分各占2字节。UDP的头部没有任何控制信息,所以UDP的传输是不可靠的。接收端接收到数据既不知道数据的发送顺序也不知道数据是否正确。

面向连接无连接服务

面向连接:在真正通讯之前,必须先建立一条通讯线路,必须先完成连接。

TCP完成连接的过程:

建立连接:三次握手

        如下图,A是客户端,B是服务器端,两端在建立连接之前都是处于CLOSED(关闭)状态。服务器永远都是处于被动等待连接的一方,因为都是让服务器帮我们干点事,而服务器不会找我们办事的。在客户连接服务器之前,服务器处于LISTEN(监听)状态,等待客户的连接(服务器一般是常驻的)。

        这里就要用到TCP报头中的标志位了。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号。而ACK报文段(即ACK=1的报文段)可以携带数据,如果不携带数据则不消耗序号。

        1> 客户A向服务器B发出连接请求,这时头部中的同步位SYN=1(此时不携带数据但消耗序号),同时选择一个初始序号seq=x。这时TCP客户端进程进入SYN_SENT(同步已发送)状态。<图中从上往下第一个箭头>

        2> B收到请求连接后,如同意连接,则向A发送确认。再确认报文段中,SYN和ACK都为1(此时不携带数据但消耗序号),确认号为ack=x+1,同时也为自己选择初始序号seq=y。这时TCP服务器进入SYN_RECV(同步收到)状态。<图中从上往下第二个箭头>

        3> A收到B的确认后,还要给B确认。确认报文段的ACK=1,确认号ack=y+1,而自己的序号seq=x+1(原因是之前已经消耗了序号x)。在这种情况下,下一个数据报文段的序号仍然是seq=x+1(原因是ACK报文段不携带数据则不消耗序号)。这时TCP连接已建立,A进入ESTABLISHED(已建立连接)状态。当B收到A的确认后,也进入ESTABLISHED状态。<图中从上往下最后一个箭头>

上面给出的连接建立过程,叫做三次握手(三次联络)

两次握手行不行???

1>如果两次握手,则服务器会不断超时重传ACK/SYN。

2>如果两次握手,有可能会浪费服务器资源,也有可能会遭到SYN溢出攻击。因为网络环境,客户端的SYN可能会重传多次,如果客户端SYN传送第一次时,报文段在网络中长时间停滞,而客户端以为数据报丢失,又一次发送SYN报文段并且与服务器建立了连接。但是若干时间后,服务器又收到了客户端发的第一次连接,它会以为客户端又给它发了一次连接,此时如果就建立连接的话,就造成了服务器资源浪费。而如果有了第三次握手,客户端就不会进行确认,服务器收不到确认就认为客户端没有要求连接。

断开连接:四次挥手

数据传输结束后,通信双方都可释放连接。如下图,A是客户端,B是服务器端,两端都处于连接ESTABLISHED(连接)状态。

这里还是要用到TCP报头中的标志位了。TCP规定,FIN报文段(即FIN=1的报文段)即使不携带数据,但也消耗掉一个序号。

        1> 客户A向服务器B先发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。这时释放报文段FIN=1,其序号为u(u=前面已传送的数据的最后一个字节的序号+1),这时A进入FIN_WAIT1(终止等待1)状态。<图中从上往下第一个箭头>

        2> B收到连接释放报文段后发出确认,确认报文段的ACK=1,确认号ack=u+1,而这个报文段自己的序号为v(v=B之前传过的数据的最后一个字节的序号+1)。然后B进入CLOSE_WAIT(关闭等待)状态。TCP服务器进程通知高层应用程序进程,因此A到B的连接就释放了(由于TCP是全双工,所以既有A到B的连接,也有B到A的连接)。这时的TCP处于半连接状态(即A没有数据要发给B了,而B若发送数据,A仍要接收,从B到A并没有关闭)。A收到B的确认后,就进入FIN_WAIT2(终止等待2)状态,等待B发出连接释放报文段。<图中从上往下第二个箭头>

        3> 若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的报文段FIN=1,ACK=1。假定B的序号为w(半关闭状态B可能发送了数据)。B还要重复发送确认号ack=u+1。这时B进入LAST_ACK(最后确认)状态,等待A的确认。 <图中从上往下第三个箭头>

        4> A在收到 B的连接释放报文后,必须发出确认。在确认报文段中ACK=1,确认号ack=w+1,而自己的序号seq=u+1(由于之前消耗掉一个序号)。然后就进入TIME_WAIT(时间等待)状态。值得注意的是:此时TCP连接还没有释放掉。必须经过2MSL(最长报文段寿命)的时间后,A才进入CLOSED状态。<图中从上往下最后一个箭头>

为什么要等待2MSL的时间??

1> 保证A发送的最后一个ACK能够到达B。如果这一报文段丢失,B没有收到确认消息就会超时重传确认报文段,接着A就会重传一遍确认报文,重新启动2MSL计时器。

2>使B发过来的报文段能够识别并丢弃(可能有迟到的报文段),等待2MSL后所有需要A接收的数据都发过来了(没过来的已经过期了)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值