0

TCP聊天室

 2 years ago
source link: https://z-rui.github.io/post/2016/09/chatroom/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

TCP聊天室

Mon Sep 12, 2016

我用Go编写了一个简单的聊天室程序。这个程序分为服务器端和客户端两部分。

服务器端用于监听主机上的端口,以便接受来自其他主机的连接。建立连接后,服务器从客户端处收集消息,然后广播到所有客户端。

客户端用于消息的输入和显示。当成功建立起到主机的连接后,输入的消息将被发送至服务器,而服务器发来的消息将被显示在屏幕上。

我用termui编写客户端的界面。虽然还有一些小问题,总体来说效果不错。

chatroom-1.png

(字符颜色只是termui的一个trick,并非我的程序用于区分身份的方式)

程序以Go写成,保证了良好的可移植性,以及对Unicode的支持。任何能够监听端口的主机都可以运行服务器。因此,这个聊天室也适合点对点通信的情况(把服务器运行在其中一个节点即可)。

当然,这个聊天室程序还很简陋,目前最大的问题是没法区分消息记录中的说话人。当然很容易解决,只要服务器端在每条广播出去的消息前面加上来源(如IP地址)即可。当然更好的办法是为每个来源分配一个标识符(用户名),这样更容易分辨。

另外一个问题是安全性。这是多方面的。首先,聊天内容通过TCP明文传输,不能保证通信安全。其次,缺少认证机制。任何主机都可以不经认证地连接到服务器,从而加入聊天室。最后,服务器的抗压能力尚未得到确认。如果遭到大量主机发起的恶意连接,很可能耗尽服务器的资源。

解决以上问题需要比较多的工作。我写这个聊天室程序只不过是为了演示,所以就没有付诸实践的打算。但是纸上谈兵还是可以的。因为我最近也在研究OpenPGP,所以我想将这两者结合应该是一个不错的办法。

首先是身份认证问题。服务器端应当保存所有可以参加到聊天室的成员的公钥。建立连接时,服务器向客户端发送一随机字符串,客户端对其签名后返回服务器,服务器验证签名无误后即接受连接。如果认证无法通过,则应该中止连接。

然后,聊天内容可以在客户端使用所有参与聊天的成员的公钥进行加密,然后发送到服务器,服务器广播到所有各个客户端,然后各个客户端再用自己的私钥解密。这样保证了通信安全。

既然已经做了身份认证,那么每个客户端已经具备了一个标识符(公钥中包含姓名和邮箱等信息),区分说话人的问题也就迎刃而解了。

Go语言已经有了现成的OpenPGP实现,想要增加这些功能应该不算困难。本地的密钥管理可以依靠GnuPG工具来完成。

除此以外还可以做一些锦上添花的工作,例如在消息记录中提供用户登入/登出的公告,或者更高级一点,能显示在线成员列表,等等。

另一个思路是SSH Chat。身份认证、内容加密等问题直接通过SSH协议解决,不需要重复造轮子。



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK