UDP踩坑——为啥老阻塞?

众所周知,UDP是尽力而为的服务,也就是传输是不可靠的,丢包不会给你重传,只会作一些简单的查错。最最最重要的是UDP没有TCP的三次握手机制!若是你们想要经过UDP传输一些文件之类的话,就须要模拟TCP三次握手,让UDP可以“活”起来,否则就会形成丢包,或者形成由于丢包而产生的阻塞。spa

  1. 踩坑①:server


    image
    图中左侧的流程中,Client端按照文件大小除以packet大小来肯定while循环的次数,这是比较致命的,由于在UDP中极有可能出现丢包的状况,那么循环的次数就不是正确的次数了,从而形成阻塞。而丢包在以太网中仍是比较少见的,可是仍是发生了丢包,这是为何呢?八成就是在在Socket创建以前就丢了!因此进而形成循环次数不对,Client苦苦等待,Server端已经发完运行以后的程序了。blog

    那么咱们应该如何解决这样的问题呢?get

    • 不用循环次数来退出while循环!而用自定的一种说明,好比Server端传完数据以后再额外发一个终止信息,Client接收到终止信息以后退出while循环,那么这样依旧可能形成终止信号丢失,Client又阻塞了...这时一个办法是采用可靠传输的TCP传送终止信号,或者经过setSoTimeout来设置超时时间,一旦超过这个时间就退出。
    • 让Server端等待Client创建Socket,创建完以后再给爷传!也是采用可靠的数据传输TCP,告知Server我已经创建链接了,您能够传输了。也就是图中右侧部分的流程。
    • 图中还有第三种解决方法就是直接让Server端sleep,可是由于时间不太好肯定,因此不太推荐。
  2. 踩坑②:

    在server端,咱们建立固定大小(如512B)的byte[] b封装咱们的dataPacket,可是文件每每不是能被完整划分的,因此最后一个文件的实际信息大小可能会小于512B。此时在Client,咱们将传输以后的文件写进本地的文件中,dp是dataPacket,里面存储着传输过来的信息byte[] b =dp.getData(),在将b写入文件时,咱们应该取0-b的实际有效信息的长度,否则会产生实际有效信息长度小于512B时,b会被自动填充前面一个dp的信息以使得b的大小达到512,这就产生了冗余it

    具体结果以下:class

    正确接收文件:循环

    image
    产生冗余以后的:程序

    image
    能够明显看到重复的文字,因此我猜想dataPacket是排队连起来的,若信息长度不够时,会拿前面一个数据包信息填充。方法

相关文章
相关标签/搜索