关于 TCP 传输发送包的策略的一个问题

2021-01-20 01:14:09 +08:00
 Zhuzhuchenyan

各位好,

小弟最近在做网游服务端,前期为了快速 DEMO 所以先选了 TCP 来承载网络连接。遇到这样一个问题

先解释一下背景,用户释放技能判定成功,服务端需要做以下几件事

  1. 广播这个技能给所有关联的客户端,
  2. 广播给所有关联客户端他们的状态改变(由于技能释放产生的玩家的状态的更改)
  3. 广播这个技能的伤害结果给客户端(因为伤害结果不仅可以由技能产生,所以这里有个单独的逻辑,当然伤害结果可以由状态改变来计算,这里为了能自定义一些功能所以没这么做)

对于这三个同时需要广播的内容,我有两种选择,

  1. 同时发送三个 TCP 包,用类似 Promise.All 或者 Task.WhenAll 的方式
  2. 将他们的有效内容黏在一起只调用一次 socket.sendbytes

(此处假设所有 socket 的 send 操作都在特定的 IO 线程,不会阻塞主线程) 这两种方式孰优孰劣呢?

假设,

我个人的理解第二种方案比第一种方案的优势在于,

  1. 节省了两个 TCP 报头
  2. 只用 ACK 一次

还望各位能提点一二

朱朱

828 次点击
所在节点    问与答
6 条回复
ryd994
2021-01-20 01:25:58 +08:00
你这就相当于手动做了 nagle 算法
你可以使用 TCP 选项强制开关 nagle
也可以用 TCP_CORK 来强制延迟某些数据
gyf304
2021-01-20 01:57:04 +08:00
TCP 概念上是流不是包,如果直接用 OS 的 TCP/IP 栈的话默认是自己会优化的 (即,调用多次 send 可能实际上只输出一个 IP 包)
TCP_NODELAY 可以防止 OS 用 Nagle 算法自行优化 (即所谓的“粘包”)
不要过早优化
djoiwhud
2021-01-20 01:57:35 +08:00
选 1,别整那些闭门造车的所谓优化。

你的需求看起来是想把三个类似比较小的 protobuf 结构合并成一个大一点的结构。明明业务层调整一下就可以满足你的要求,为何要在传输层调整?

最根本的一点,整乱七八糟的“优化”会大幅度降低稳定性和代码的可读性。关键是,这每个包才多 46 字节。

另外,你对网络特性和实际上线后期维护的处理都看着经验不足,企业怎么放心让你一个人搞的?
henvm
2021-01-20 01:58:47 +08:00
我记得网络分单播,广播,组播。可以尝试组播
gyf304
2021-01-20 02:00:48 +08:00
@henvm TCP 没法组播广播的 再说客户端和服务端肯定不在一个广播域
Zhuzhuchenyan
2021-01-20 02:14:32 +08:00
感谢各位,那我还是维持原状比较好。

@djoiwhud 不是给公司搞的,自己做的小项目,我本职是前端程序员,对网络特性也是在边翻书边学的状态。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/746491

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX