创建协作白板绘图应用程序
我有一个自己的绘图程序,里面有各种“绘图工具”,比如铅笔、橡皮擦、矩形、圆形、选择、文本等等。
这个程序是用Python和wxPython做的。上面提到的每个工具都是一个类,它们都有一些多态的方法,比如left_down()、mouse_motion()、hit_test()等等。程序会管理一个所有绘制形状的列表——当用户画了一个形状,它就会被添加到这个列表中。这个列表也用于管理撤销和重做的操作。
所以,我有一个不错的代码基础,可以在上面加入协作绘图的功能。每个形状可以被修改为知道它的拥有者——也就是画这个形状的用户,并且只允许这个用户对自己画的形状进行删除、移动或缩放操作。
我在想,开发这个功能的最佳方法是什么。在“会话”中,必须有一个人充当服务器,我没有钱去提供免费的中央服务器。用户需要某种方式连接到服务器,这意味着需要一种“发现服务器”的浏览器……或者其他什么方法。我该如何广播对应用程序所做的更改?实时绘图并在每次鼠标移动事件时广播消息在性能上会很耗费资源,而且用户越多,情况就越糟。
欢迎任何想法,我不太确定从哪里开始开发这个功能(甚至如何测试它)。
1 个回答
制作任何实时协作工具或游戏,关键在于高效地同步客户端之间的共享数据。 网络带宽是一个瓶颈。只发送绝对必要的信息来同步共享数据。你选择存储形状而不是单个像素是个好主意。不过,形状不应该直接处理鼠标事件。正如你所提到的,广播鼠标事件会迅速占满网络带宽!相反,应该传递形状是如何被鼠标事件改变的。例如,不要发送鼠标移动的每一步,而是发送形状移动后的最终位置 [x,y]。
我建议将你的绘图程序分为服务器部分和客户端部分。 服务器保持共享数据的权威版本。客户端永远不直接操作共享数据结构;它只向服务器发送网络消息。虽然在同一个进程或电脑上这样做似乎有点傻,但其实有一些很好的理由:
- 可以共享代码路径,适用于单用户和多用户。
- 在同一个进程中,客户端和服务器之间的网络开销几乎为零,使用本地套接字时尤其如此。
此外,编辑不必仅限于形状的拥有者。由于服务器是最终的权威,当两个人同时操作同一个形状时,服务器会解决冲突,并将结果发送回客户端。(不过,撤销操作会有点棘手。)
虽然集中式服务器最适合网络发现,客户端也可以使用其他方法来找到服务器:
- 发送或监听网络 广播数据包。
- 通过IP地址直接连接。(服务器的IP地址需要通过其他方式传达:聊天、手机、在房间里大喊、信鸽等等。)
最后,看看其他多用户应用是如何设计的。这里有一些例子:
- Zoidcom 多人游戏编程库(C++)。这个回答的很多内容都基于Zoidcom文档的信息。还有示例程序展示了如何通过网络广播发现服务器。
- 操作变换 算法,Wave和Google Docs背后的技术。(文章 讨论 在Hacker News上。)
- Etherpad 开源实时协作文本编辑器。
- Source Multiplayer Networking 解释了像《半条命》这样的第一人称射击游戏是如何设计的,并介绍了一些减少延迟的技巧。
- Google Wave (显然文档仍然相当糟糕...)