网络上用udp协议进行文件传输,自己加差错控制,和tcp相比哪个好,还有是每发一个包,就停止等待,还是连续发送划算

愤怒对抗喳喳 2001-07-28 10:30:24
如果连续发送要加上许多控制,而且仍然需要等待应答,能提高吞吐效率吗
...全文
2079 68 打赏 收藏 转发到动态 举报
写回复
用AI写文章
68 条回复
切换为时间正序
请发表友善的回复…
发表回复
snakecobra 2001-09-16
  • 打赏
  • 举报
回复
找《计算机网络(第三版来)》看看不就ok?
OK_boom 2001-09-16
  • 打赏
  • 举报
回复
用TCP/IP吧。
比较保险一点.
Julienjut 2001-09-03
  • 打赏
  • 举报
回复
回 flywhc(午夜蓝调) :
我现在要做的也是一个多播的程序,服务器给多个客户发送一个文件,而且有一种情况,起初服务器不知道有几个 client ,在服务端进行确认时,是直接用UDP发过去,还是广播过去也是一个问题。在server端如果要处理重发是不是要建一个监听线程,你的程序是不是在发送完所有的包后再发送出错的数据。
我的Email是 julienjut@163.com
能把你的代码发给我参考一下吗
到我的那个帖子去交流一下了!这个帖子太多了,而且还没有分。
我的帖子是“谁有安全UDP的算法,谢了!好的想法也可!(Julienjut)”
Julienjut 2001-09-03
  • 打赏
  • 举报
回复
回 Adward_Lao(老锄头) :
我的程序中也有一个这样的问题,不加Sleep()好象发生丢包的概率要高很多,加了以后就好的多,有时候没有一个丢包的情况发生!而且这个情况在我做TCP、UDP的过程中都有发生。
flywhc 2001-08-14
  • 打赏
  • 举报
回复
如果你用一般的API,文件I/O都是自动缓冲的。Seek开销并不大。

Sleep(n)太武断了。应该有自动降速提速的算法。在DOS时代,有个Z-MODEM协议用于串行通讯,就是如此。当丢包增多时就降速,一段时间不丢包时则增速,当然有个延迟过程,简单的比例算法即可。工业控制上有个比例、积分、差分算法,更精确,不过上学时学的现在忘了 :(
Adward_Lao 2001-08-14
  • 打赏
  • 举报
回复
我的以上算法主要考虑是尽量降低客户端开销,因为反复的磁盘I/O(每次收到都要Seek、Seek,因为是文件发送,不可能开内存缓冲区)可能影响取包的速度(包的丢失决大多数是来不及取,而挤爆了缓冲区),导致包丢失率更大,我的算法中磁盘I/O是最少的(顺序写),实际上增大发送端开销,降低接收端开销(我甚至考虑去掉接收端的CheckSum,在同一网段下,还没发现有CheckSum错的情况,但去掉之后又惴惴然不安也,还是加上吧),对流量控制有益,已从实验看出在LAN中,没有流量控制的连续发送的丢包率大得惊人(我猜测,接收端的出错响应会不会被淹没在繁忙的数据流量中),但如果在每次发送之后Sleep(1)(没有错,是1,发送1M也不过延迟了一秒,当然这只是最简单的一种控制方式)其效果非常明显,可以说非常顺畅,在网络质量好时,几乎就没有几个包丢失,即使在繁忙的网络中,其效率也远好于不控制的算法,七嘴八舌的来回响应本身就可能产生网络风暴,这已在实践中得到证实。
再说明一下上面的改进算法,在实现过程中才发现,接收端根本无法判断后续的4、5是惯性,还是发送端根本没有接收到响应而洋洋自得地在继续发送,如果接收端只有一个,那就惨了,直到兴冲冲地发送完才接到通知,同志,怎么就结帐了,二月份的工资都还没发呢。如果客户多一些,反倒不会出现这种情况。由此又衍生出两种修正算法,复杂些,对不同的状况效率有所不同,就不多说了。
总的来看,没有流量控制的UDP再好的错误控制算法都只是杯水车薪,如果有好的算法,再加上哪怕最简单的流量控制,效果都要好得多,目前,我的文件多播就是采用可靠的算法(接收到的文件肯定是正确的),再加一个Sleep(?)。在不同的状况下性能也只有少许差异,但总体效果还是相当不错的。
cai3995 2001-08-14
  • 打赏
  • 举报
回复
O
flywhc 2001-08-13
  • 打赏
  • 举报
回复
老锄头的问题,在LAN里网络质量那么好,错误多一定是因为发的速度太快了,有个自动降速的机制就好了。
用多点同传的思想也许会好。如果包3丢了,4,5..却不必丢弃,服务器补发包3即可,不必把4,5包也重发,两边可以都有个丢包的纪录列表,每隔一段时间(比如1秒)再请求/重发一次
Adward_Lao 2001-08-11
  • 打赏
  • 举报
回复
如果作为单播,当然TCP是首选(如果系统有特殊要求除外),但如果是在多播情况下(如网络教室应用里,教师机多播到学生机),使用UDP似乎是理所当然的,这种情况下如何进行差错控制。我曾经写过一个多播文件传输:服务端首先多播文件头信息,等待所有客户确认,然后连续发送数据,同时接收客户的出错响应,如出错就返回到出错位置继续发送,客户端按序号接收并顺序写入文件,如序号超前就发出错响应,对于重发数据(序号落后)就丢弃,最后服务端发文件结束标志,等待所有客户确认,当然还有校验和、超时控制等。这样下来,三两个客户的传输性能要好于TCP的分别传输,但当客户数量增加到五六个时性能就大不如前了,究其原因,发现该算法有一个致命的缺陷,比如1、2、3、4、5、6连续发出后,客户端丢失3但后续的4、5、6都收到,这样在收到4、5、6都发3出错响应,服务端发出6之后会连续收到三个3出错响应,并三次折返重发3,而实际上只需一次,但客户端又不能判断在什么时候该重发3,因为可能它连重发的3也没能收到,而服务端重发3之后已向前进了。所以如不出错(网络质量相当好,文件又小),性能相当不错,但一旦客户量增加,发生几次错误,性能立马降下来,反不如TCP轮发。
最近又想到一个改进算法,即再增加一个由服务端维护、一直累加的重发计数,对于惯性产生的5、6重发计数同4就丢弃,如超前再发出错响应,同样如果几个客户同时丢失了同一个包,服务端在收到对同一个包的几个出错响应时判断重发计数,如果响应中的重发计数小于当前的重发计数则忽略,如大于再重发,想来改进之后的算法对性能的提升很有益,但目前还没有实现,效果未知,过两天闲下来再试试。
对于上述算法,不知大家有何高见,探讨一下。TCP和UDP的目标不同,因此应用的场合也不同,相比于TCP我觉得UDP最大的优势是多播及广播,当然还有速度、无连接等优越性(如果黑客程序利用UDP会更具隐蔽性),随着网络质量的提高,多媒体应用的进一步发展,UDP的应用还会逐渐增加。
api303 2001-08-09
  • 打赏
  • 举报
回复
to flywhc(午夜蓝调): 
你搞过UDP的视频传输开发吧:能否给我谈谈你的思路!谢谢!!
jcsun 2001-08-09
  • 打赏
  • 举报
回复
其实你所说的就是TFTP,unix中存在的服务。
代码在许多编程的书上都有,可以参考一下。

flywhc 2001-08-09
  • 打赏
  • 举报
回复
to duuyuu: 如果第65535个包已经发出而第0个包经过如此长时间的反复重发仍然没有发到,那这个连接可以说根本不能用了。如果是tcp连接,在这种环境下早已超时断开连接了。
udp的另一个好处是无连接,也就不存在断开连接的情况,对于网络环境差的地方,tcp需要反复的连接、断开、连接、断开……我想大家都知道建立一个tcp连接需要反复传许多次包,可能刚刚连接上立刻就断了,数据根本传不过去。而udp总有“漏网之鱼”发到目的地。

好像你跑题了哦,这里说的是传输文件,文件的大小是有限的。

的确要确认,每N个包回复一次的话,对于高质量的网络环境,尤其非对称的ADSL中是很浪费流量的。因此可以改善一下我上次所写的,每隔几秒发一次确认,告诉发方已经收到的文件长度 -- 这也解决了"65535"溢出的问题。

to cai3995: 再仔细想一想,如果用于传输文件的话,算法够好,无论网络质量好还是坏绝对udp要比tcp好。tcp太重同步和数据安全性,是一种普遍性的,对于大文件传输并没有优势。

to api303: 不是,我做过类icq系统。

tencent的系统混合使用udp和tcp,结果它的文件传输效率低下,特别是网络质量差的情况,而且如果两个client分别在不同的proxy/NAT后,就无法传输文件了。
为了解决这个问题,我写了udp传输文件的程序,两个问题同时解决了。当时我们从科研网的一个linux NAT后的一台PC向Chinanet出口的一个MS proxy后的一台PC传文件,Oicq根本不允许传,而我的程序能看到进度条一秒不停地持续前进,中间虽然也有错包,但文件却是正确的。大家都知道,oicq传输文件总是传一会停顿一下的,即使网络质量好也是,网络质量差时简直跟死了似的,半分钟才跳一下。

cai3995 2001-08-09
  • 打赏
  • 举报
回复
就像木易说得那样,UDP适用于允许一定错误的环境,比如网络视频会议,我可以丢包,但是一定要保证实时性,我就需要使用到UDP了,但是类似于下载的话,我丢那么多包后,请求发送端重发,结果效率反而下降。
cai3995 2001-08-09
  • 打赏
  • 举报
回复
2flywhc(午夜蓝调): 
只要有丢包,收端就不断的发重发请求,总有发到的时候。
你的网络环境好当然了,在低劣的环境下,有可能效率反而比TCP还要低的,虽然你说的还是有道理的,但是具体使用还是要看实际情况。
duuyuu 2001-08-08
  • 打赏
  • 举报
回复
flywhc(午夜蓝调): 
如果收方始终不给确认,发方永远无法知道收方已经处理到了几号包。
以最大65535为例:
如你所说,发方发到了65535号包,下一个只能循环回来用0作序号,但是发方并不知道收方是
否已经处理完了上一个0号包,它怎么能冒然的使用0序号呢?如果它这样做了,这个程序便
是不严密的!在发方速度很快而收方速度很慢的时候肯定会出错的,很有可能出现发方发出
的包比收方处理到的包超前很多的情况,可能发方发到了n号,而收方还没来得及处理上一个
循环的n号包,此时就重号了!

即使你用了4个字节,甚至100个字节来存放序号,也不行,因为我们的通信往往不是传
一个文件了事,比如有一个应用需要发方和收方常年累月的持续进行琐碎的通信,一次通信
可能持续几个月(许多监控程序就是如此)无论你的序号多大,都会溢出的!
所以为了严密,同步确认是一定要有的,我觉得为了提高效率,收方可以每100个或更多的包
给一个确认,既弥补了tcp的低效,又保证了程序的严密性!
以上是拙见,欢迎大家指正。
flywhc 2001-08-08
  • 打赏
  • 举报
回复
to cai3995(塞尔):
重传的请求丢了也没关系。在我以前写的程序里,只要有丢包,收端就不断的发重发请求,总有发到的时候。当然这也会造成重包,丢了就成了。

to duuyuu:
如果用2字节长的ID,当然只有65536个包,
但我用4个字节长作包的ID,每个包有500字节数据,你算算能传输多大的文件?

而且,这个ID事实上是循环使用的,不可能等到第65535包传到的时候第0包仍然没有到,除非已经断开连接。判断连接是否已经断开,可以让收端每几秒发回一个无用的包告诉发端仍然可以连接。
duuyuu 2001-08-02
  • 打赏
  • 举报
回复
to flywhc(午夜蓝调):
tcp中,发方和收方是同步的。
你的这种模式,发送方和接收方是异步的,
那么就有一个问题:如何标识丢失的包?发方不停的发数据,收方发现有丢包时,
通知发方重发,可是怎么让发方知道重发哪个包?只有发方给每一个发出的包都加上一个
序号,但是这个序号无论多大,总有限制,例如序号最大65535,那么第65536个包怎么标示?
用最小的序号0表示?那么如果恰好此时收方要求重发0号包,到底重发哪一个呢?
异步方式虽然速度快,但是怎么解决上面的问题呢?
cai3995 2001-08-02
  • 打赏
  • 举报
回复
但是你要考虑到dai_zz(渣渣) 是在一个很大,干扰比较多的大网络环境下
“无论哪一方发消息,对方都有可能收不到”这就不是一个少数情况了,重传的请求很有可能就会丢失的。所以他选择tcp
flywhc 2001-08-02
  • 打赏
  • 举报
回复
不同意上面的说法。Tcp协议是考虑普遍的情况,效率不高。
对于特殊的应用,比如点对点传输大文件,UDP可以达到很高的速度。

校验几乎不消耗流量,重发只是少量的。计时器只需要简单的+1操作而已。

如果你真的作过,就会发现UDP其实是很好用的,只是编程麻烦一些,要算校验等,但这些只是消耗CPU而已。

“无论哪一方发消息,对方都有可能收不到”这只是少数的情况。而TCP为了等待这少数的情况
却要等待半天。而如果是UDP协议,无论是是否遇到错误都继续发数据,不需要确认。
这样即使丢了几个包也无所谓,不耽误时间。

比如,发送 1, 2, 3,4,...第3个包丢了,接受者请求第三个包,而发送者在收到这个请求以前仍然发送第4,5,6...收到请求后则补发第三个包,时间一点都没耽搁。

如果用TCP,虽然你的程序不用考虑这些,其实在后台,却要在第三个包上等待重发,耽搁许多时间
cai3995 2001-08-01
  • 打赏
  • 举报
回复
to: wangledong(快乐的程序员) 
"建议有接收方驱动,或发送方一直发送,有接收方进行校验,有错误才通知接收方重发"
一拍即合:)
我希望能发送端加上发送列表,发送完毕再由接收方对照发送列表检测将结果返回发送端,请求重发。应该可行吧
加载更多回复(48)

4,356

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧