UDP 和 TCP 的 socket 分别一般用在什么地方?

关注者
2,118
被浏览
453,854

70 个回答

UDP 的使用范围很窄,而且编程比 TCP 难多了:

  1. 你真的很在乎延迟,不能忍受重传,那么就用UDP,例如 NTP 协议。重传NTP消息纯属添乱。
  2. 你真的不在乎可靠性,丢一些包也不需要重传,那么就可以用 UDP。例子我想不出来。有人说音频或视频流可以用UDP,不过据我看来各大视频网站都用HTTP协议,而HTTP是基于TCP的。
  3. 你需要NAT穿透,那么不得不用UDP。
  4. 其他情况,一旦程序要自己做重传,你都是在用UDP模拟出蹩脚的TCP,还不如直接用TCP呢。

总之:使用 UDP 需要有强大到不容置疑的理由,when in doubt, use TCP.

一些协议,出于历史原因,受当时技术和网络条件限制,选择了基于UDP实现,其选择的理由现在很可能已经不再成立了。因此“xxx协议用UDP”不是你现在写网络应用程序也该用UDP的理由,除非你本身就是在实现xxx协议。

另外,那些说TCP比UDP慢、效率低的,你拿UDP写个程序,把千兆网带宽打满(TCP等价的代码只有两行:客户端 while (true) { send(...); } 服务端 while (true) { recv(...); }。),且不说你的程序会有多复杂,先看看goodput到底是不是比TCP大、CPU使用率是不是比TCP低嘛。

最怕就是对端udp重用了一下端口, 造成的串包(对端不想和我通信了,把socket 关了,然后新建了一个socket又把这个端口占了,然后我又还傻呵呵的和这个socket通信,以为还是原来那个兄弟,有时候这种状态要解出费劲死了。。)

其实我认为最关键的就是:


通信其实真的是个有状态的事情。

传输却是个无状态的事情(努力收发吧)。

当使用udp做通信的时候,应用层在做通信,而内核认为自己在做传输。基层的理解小于了上层,上层要费姥姥劲儿才能把这个谬误给纠正过来。

当你理解了上面说的这些的时候,你就可以明白,为什么TCP的关闭是如此的复杂;你每少理解了其中一个要素,几乎都会在udp通信中把亏给吃回来,所以我的建议是:

TCP做通信(尤其是点对点的,双向通信的)

UDP做传输(push 流, 不可靠地push状态更新, push app tips, 订阅/发布者模式...,) 什么是传输?最简单的理解就是单向通信,单向推送,。。。无状态如滔滔大江一去不复返,不用记得某滴水上次流到哪里了,也不用管水最终流向何方(我有进入傻子模式见笑了)。

拿udp上面做tcp通信的时候,或者说你认为你比设计tcp的那些前辈能设计出更符合你业务场景的通信协议时,请先保证:你真正理解了tcp的设计,到底是在为了解决哪一些问题(很抱歉,这个问题的答案,很少有教科书能够逐点并结合用户态编程实际来进行阐述。).