美文网首页
【JAVA】 浅谈TCP&UDP

【JAVA】 浅谈TCP&UDP

作者: Y了个J | 来源:发表于2018-09-21 13:57 被阅读64次

    TCP与UDP区别?
    udp:
    a、是面向无连接, 将数据及源的封装成数据包中,不需要建立连接
    b、每个数据报的大小在限制64k内
    c、因无连接,是不可靠协议
    d、不需要建立连接,速度快
    tcp:
    a、建议连接,形成传输数据的通道.
    b、在连接中进行大数据量传输,以字节流方式
    c、通过三次握手完成连接,是可靠协议
    d、必须建立连接m效率会稍低 聊天、网络视频会议、桌面共享用的就是 udp

    Q:为什么说TCP报文段是面向字节流的,UDP包是面向数据报的?

    “TCP是一种流模式的协议,UDP是一种数据报模式的协议”,这句话相信大家对这句话已经耳熟能详~但是,“流模式”与“数据包模式”在编程的时候有什么区别呢?

    面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会使IP太小。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。

    虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

    Q:TCP协议如何来保证传输的可靠性和数据的顺序性?

    TCP提供一种面向连接的、可靠的字节流服务。
    面向连接:意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP。 应用数据被分割成TCP认为最适合发送的分组,A为发送方,B为接收方。可靠传输原理是以下两个协议:
    1、停止等待协议:每发送完一个分组,就停止发送,等待对方的确认,收到确认后再发送下一个分组。
    (1)出现差错,采用超时重传功能,若B检测到收到的分组有错,就丢弃此分组,什么也不做(TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化),A在发送后就设置一个超时定时器,若超过定时器时间还没有收到确认,就重新发送此分组(注意:A发送完一个分组后必须保留副本,为超时重传使用;分组和确认分组都要进行编号;超时重传时间必须大于一个往返时间);
    (2)确认丢失和确认迟到:B发送的确认丢失或迟到后,A过了超时定时器的时间,就重新发送分组,B丢弃这个分组,同时向A发送确认;
    上述的确认和重传机制,称为自动重传请求ARQ协议;
    2、连续ARQ协议:利用发送窗口,位于发送窗口内的所有分组都可以连续发送出去,而不需要等待对方的确认。A每收到一个确认,就把发送窗口向前滑动一个分组的位置。B采用累积确认方式,对按序到达的最后一个分组发送确认,就表示到这个分组之前的所有分组都收到了。

    保证数据的顺序性:
    既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。 (对失序数据进行重新排序,然后才交给应用层)

    屏幕快照 2018-09-21 下午2.01.42.png
    Q:说说三次握手?

    第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
    第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
    第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
    完成三次握手,客户端与服务器开始传送数据。
    通俗的描述:client对service说我要建立连接啦,service回应说你连接吧,client收到回应后把自己状态改为established,然后告诉service我已经准备好了,然后service也把自己状态改为established。

    TCP粘包,拆包及解决方法

    在进行Java NIO学习时,发现,如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况,这就是TCP协议中经常会遇到的粘包以及拆包的问题。
    我们都知道TCP属于传输层的协议,传输层除了有TCP协议外还有UDP协议。那么UDP是否会发生粘包或拆包的现象呢?答案是不会。UDP是基于报文发送的,从UDP的帧结构可以看出,在UDP首部采用了16bit来指示UDP数据报文的长度,因此在应用层能很好的将不同的数据报文区分开,从而避免粘包和拆包的问题。而TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界;另外从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段,基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。

    粘包、拆包发生原因

    发生TCP粘包或拆包有很多原因,现列出常见的几点,可能不全面,欢迎补充,
    1、要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
    2、待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
    3、要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
    4、接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。

    粘包、拆包解决办法

    相关文章

      网友评论

          本文标题:【JAVA】 浅谈TCP&UDP

          本文链接:https://www.haomeiwen.com/subject/awmanftx.html