TCP聊天室
我用Go编写了一个简单的聊天室程序。这个程序分为服务器端和客户端两部分。
服务器端用于监听主机上的端口,以便接受来自其他主机的连接。建立连接后,服务器从客户端处收集消息,然后广播到所有客户端。
客户端用于消息的输入和显示。当成功建立起到主机的连接后,输入的消息将被发送至服务器,而服务器发来的消息将被显示在屏幕上。
我用termui编写客户端的界面。虽然还有一些小问题,总体来说效果不错。
(字符颜色只是termui的一个trick,并非我的程序用于区分身份的方式)
程序以Go写成,保证了良好的可移植性,以及对Unicode的支持。任何能够监听端口的主机都可以运行服务器。因此,这个聊天室也适合点对点通信的情况(把服务器运行在其中一个节点即可)。
当然,这个聊天室程序还很简陋,目前最大的问题是没法区分消息记录中的说话人。当然很容易解决,只要服务器端在每条广播出去的消息前面加上来源(如IP地址)即可。当然更好的办法是为每个来源分配一个标识符(用户名),这样更容易分辨。
另外一个问题是安全性。这是多方面的。首先,聊天内容通过TCP明文传输,不能保证通信安全。其次,缺少认证机制。任何主机都可以不经认证地连接到服务器,从而加入聊天室。最后,服务器的抗压能力尚未得到确认。如果遭到大量主机发起的恶意连接,很可能耗尽服务器的资源。
解决以上问题需要比较多的工作。我写这个聊天室程序只不过是为了演示,所以就没有付诸实践的打算。但是纸上谈兵还是可以的。因为我最近也在研究OpenPGP,所以我想将这两者结合应该是一个不错的办法。
首先是身份认证问题。服务器端应当保存所有可以参加到聊天室的成员的公钥。建立连接时,服务器向客户端发送一随机字符串,客户端对其签名后返回服务器,服务器验证签名无误后即接受连接。如果认证无法通过,则应该中止连接。
然后,聊天内容可以在客户端使用所有参与聊天的成员的公钥进行加密,然后发送到服务器,服务器广播到所有各个客户端,然后各个客户端再用自己的私钥解密。这样保证了通信安全。
既然已经做了身份认证,那么每个客户端已经具备了一个标识符(公钥中包含姓名和邮箱等信息),区分说话人的问题也就迎刃而解了。
Go语言已经有了现成的OpenPGP实现,想要增加这些功能应该不算困难。本地的密钥管理可以依靠GnuPG工具来完成。
除此以外还可以做一些锦上添花的工作,例如在消息记录中提供用户登入/登出的公告,或者更高级一点,能显示在线成员列表,等等。
另一个思路是SSH Chat。身份认证、内容加密等问题直接通过SSH协议解决,不需要重复造轮子。