113-给 udp 增加可靠性(一)

先说一些题外话。

第 112 篇到这一篇,跨越了半年多时间。

并是说真的忙到了没时间写,中间因为毕业,找工作忙活了一阵子,导致写作被中断,后来就不了了之了~重新拾起笔需要很大有勇气。(因为我自己也快忘记了^_^)。不过这半年多时间,博客的阅读量涨到了 20W+ 也算是对我的鼓励,多次想要回归继续写作,却都放弃了,因为网络编程实在是太难了。

说起来挺有意思,实际上给 udp 增加可靠性早在 17 年 6 月份程序就已经写好了。但是如今我自己重新拿起那份代码的时候,却看到了恐惧,因为我自己已经完全记不得我当时写的是啥。

经过一番挣扎,我决定重新缕一遍代码。请相信我,现在我又重回到初学者了,也许看到这一篇的你,比我还熟悉我的代码。

为了给自己预热,这一篇我打算分成两部分写。第一部分先介绍一下简单的原理,第二部分讲具体实现。

1. 为什么不使用 tcp ?

给 udp 加可靠性,不就是弱鸡的 tcp 么?还不如直接使用 tcp 协议,话是没错,但是 tcp 是以牺牲了时延为代价换取的可靠性。换句话说, tcp 通过反复重传换取了可靠性。但是在很多实时性要求非常高的领域,比如音视频、实时对战游等,如果出现这种延时是无法忍受的,因此完全使用 tcp,可能并不能尽人意,所以才有了这些方案。

在音视频领域,并不需要绝对可靠,只要尽量可靠就行,比如重传 3 次还不行,放弃算了,丢一帧图像并不会带来什么损失。

2. 可靠性如何保证

借鉴 tcp 超时重传的思路,其实很容易想到如何来保证 udp 程序的可靠性。


这里写图片描述
图1 一种可靠性保证的机制

图 1 中所示的案例相信每个人都有经历。班长发通知消息的时候,你肯定是要回复类似“收到”这样的内容的。如果你班长等了一会儿发现你没回消息,估计会发火~~~当然有耐心的班长可能会觉得你没收到,又会再发一次,直到你回复“收到”为止。

再举一个有意思的例子就是一对情侣,如果是异地恋,那肯定经常通过QQ或短信交流了。如果女方给男方发信息,男方没有回复,女方肯定就觉得对方是没有看到,或者没有收到~~~这时候女方就疯狂的“重传”,直到男方回复为止。

udp 协议和发短信非常类似,它是不可靠的。客户端发送一个报文出去后,并不能确认对端是否收到,唯一的解决办法就是对方回复确认。如果在约定的时间里对方不回复,客户端就认为对方没有收到,于是重传报文。

3. 程序伪代码

  • 客户端
// client
def client(sockfd):
    timeout = 1000 // 1000 ms
    while true:
        send(sockfd, {id:1001, msg:"hello mars!"})
        data, err = recv(sockfd, timeout)
        if err == Null and data.id == 1001: // 只要不超时,且收到的报文序号一致,就退出循环
            break
  • 服务器

服务器主要工作就是把收到的消息原封不动的再发送回去。

// server
def server(sockfd):
    data = recv(sockfd)
    send(sockfd, data)

4. 总结

掌握了上面的原理后,其实你完全可以自己写出一个简单的可靠 udp 出来。不过下一节,会给出一个 C 语言实现的完整的程序。

这里列举一些给 udp 增加可靠性的开源库:UDT, ENET, RakNet

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值