name5566 / leaf

A game server framework in Go (golang)
Apache License 2.0
5.26k stars 1.31k forks source link

关于消息头len的问题 #178

Closed trist725 closed 4 years ago

trist725 commented 4 years ago

看了下源码,发现使用TCP协议时,先读取len,再读取data,而websocket协议本身做了分包,因此不需要先读len。 那么在定义C/S消息格式时,需要区分使用tcp就发len,而使用websocket就不发len吗?既然processor已经屏蔽了分包的细节,却又要使用者区分tcp/websocket协议去发不同格式的消息,这样设计是否会有一种逻辑上不连贯的感觉?

name5566 commented 4 years ago

Leaf 的使用者(服务器的逻辑代码开发者)并不需要区分 tcp 还是 websocket 协议。Leaf 支持 tcp 和 websocket,甚至同一服务器可以同时连接 tcp 和 websocket 客户端。

trist725 commented 4 years ago

可是我看network中的实现,websocket是没有先读或写len这个操作的,服务端使用leaf发消息是可以不管,因为leaf屏蔽了这些细节,但是客户端如果不是用leaf这个包,还是需要区分是tcp还是websocket来考虑是否在包头加上len呀?

trist725 commented 4 years ago

也就是说,在tcp下,消息格式是len-id-data,在websocket下,实际上是id-data,不知道我有没有理解错。 那么客户端更多情况下是不会用leaf中的network包的(因为常常是其它语言),这时候客户端需要根据协议发不同结构的包,才能正确地和leaf服务端通信。

15951836388 commented 4 years ago

客户端,肯定是先要确定用tcp还是ws。 本身ws就不需要len,可以优化效率,所以代码不同 你非要一致,就改下leaf的代码

trist725 commented 4 years ago

客户端,肯定是先要确定用tcp还是ws。 本身ws就不需要len,可以优化效率,所以代码不同 你非要一致,就改下leaf的代码

你说的没错,但我们现在讨论的问题是,这样设计是否逻辑上有点不连贯,因为增加了使用者的心智负担。对服务端来说,一方面不需要leaf使用者了解分包细节,一方面又需要使用者读懂理解这块代码,然后告知客户端确切的消息结构,如此双方才能正确通信。

name5566 commented 4 years ago

客户端对接 Leaf 或者对接其他服务器(包括 http 服务器,甚至于不同服务),必定需要按协议规则实现(但,我不认为对接 http 服务器需要把 http 实现代码看了,也不需要看 http 服务器的逻辑代码)。要求服务器协议用同一种模式是不可能的,http 协议,tcp 协议,ssh 协议,没有哪个协议是一致的。对于客户端来说,它使用了 tcp 一般都不用考虑 ws,就像客户端学习了 tcp 协议和 tcp 服务器通讯以后,不用把 ssh、ftp 协议学了一样。

换而言之,对任何客户端来说,它通常只需要认识一种协议,它可以根据自己的情况选择,Leaf 可以灵活的加入 udp、kcp 协议等其他各种协议,但每次新增加对客户端没有学习成本,他们只需要关心自己使用的(比如说,Leaf 如果更新增加了 udp 协议,客户端之前是使用 tcp 协议,这种更新和他完全无关)。对服务器来说,无论加入或者改变任何协议,对逻辑开发也没有任何改动。

trist725 commented 4 years ago

客户端对接 Leaf 或者对接其他服务器(包括 http 服务器,甚至于不同服务),必定需要按协议规则实现(但,我不认为对接 http 服务器需要把 http 实现代码看了,也不需要看 http 服务器的逻辑代码)

我认为问题就出在这里,既然leaf封装了tcp的分包细节,却又对websocket没有封装(固然是websocket本身有这功能),那么使用者是否会很困惑,leaf什么时候封装了一些事,什么时候没封装?这不是需要去看leaf/network模块中的具体实现吗?那是不是还不如都不封装,让使用者自己决定是否要在tcp前加len?(先读len再读data并不是tcp的一部分,也不是唯一做法)

trist725 commented 4 years ago

或者也可以都封装,比如websocket解析时候忽略这个len,不过这样势必会影响效率。

15951836388 commented 4 years ago

别纠结了,开源的框架,不习惯的地方,可以自己改啊。

name5566 commented 4 years ago

任何协议都需要看文档的,具体可以看:https://github.com/name5566/leaf/blob/master/TUTORIAL_ZH.md

这里包含了范例代码。

你说的这个问题和设计没有关系。如果你直接使用 tcp,你依然需要和服务器约定具体的格式,通过口头或者文档的形式告知客户端使用方法,这个步骤是无法通过任何手段跳过的。ws 使用便利是因为无论是 unity 还是 h5 还是其他语言都按 ws 的标准做了实现,最后你调用一下具体的接口即可。对于对接 Leaf 的服务器,自然也可以按 Leaf 标准封装到 unity 或者 h5 中给其他使用者使用。

对于仅仅使用 ws 的用户,这是非常简单的使用,任何劣化都没有价值。

trist725 commented 4 years ago

找到了wiki说明,鉴于这个讨论,建议将wiki中 客户端如何对接服务器放到README或更显眼的位置