基于UDP的网络聊天室
聊天室是早期网络交流常用的软件之一,也是如今大多通讯软件配备的基本功能。聊天室可接收并显示由不同成员发送的聊天信息,如图1就是一个简单的聊天室界面。
图1 聊天室界面示例
图1所示的聊天室界面主要分为两部分,第一部分是一个聊天窗口,用于显示接收到的不同聊天室成员发送的消息;第二部分是一个编辑框,用户可在此框中编辑消息,发送到聊天室中。虽然这两部分出现在同一个界面中,但实际上他们是聊天室的两个功能,需要由不同的程序实现。
聊天室一般基于UDP协议。以上所示的聊天室中,聊天窗口是一个基于UDP协议的服务器,编辑框则是一个基于UDP协议的客户端。聊天窗口应可接收编辑框发送来的数据,并将发送数据的地址以及数据打印到聊天室中,下面通过简单代码来展示UDP聊天室的实现方式。
作为服务器的UDP聊天窗口实现如下。
import socket
def main():
# 1.创建socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.地址绑定
server_socket.bind(("", 3456))
# 3.接收数据并打印
print("-------UDP聊天室-------")
while True:
recv_info = server_socket.recvfrom(1024)
address = recv_info[1][0] + ':' + str(recv_info[1][1])
print("%s" % address)
print("%s" % recv_info[0].decode("gb2312"))
# 4.关闭聊天室套接字server_socket
server_socket.close()
if __name__ == '__main__':
main()
执行代码,结果如下所示:
-------UDP聊天室-------
此时服务器已启动,为测试服务器接收与处理客户端数据的功能,下面实现一个消息编辑发送功能的客户端。客户端的具体实现如下:
import socket
def main():
# 1.创建客户端socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2.向服务器发送数据
print('----输入框----')
while True:
data = input()
client_socket.sendto(data.encode("gb2312"),
("172.16.43.31", 3456))
if data == '88':
break
# 3.关闭client_socket
client_socket.close()
if __name__ == '__main__':
main()
客户端程序中的IP地址“172.16.43.31”为服务器所用主机的IP地址,即本机的IP地址,读者在进行测试时,需传入个人主机的IP地址。个人主机的IP地址可在命令行中使用ipconfig命令查看(Linux系统中采用ifconfig命令查看)。
执行客户端程序,客户端的执行结果如下:
----输入框----
此时可通过客户端向聊天室中发送数据,示例如下:
---输入框----
你好
之后聊天室中打印的信息如下:
-------UDP聊天室-------
172.16.43.31:50873
你好
观察打印结果,发现其中新增了两行数据,第一行“172.16.43.31:50873”为客户端的IP地址和端口号50873,该端口号由系统随机分配;第二行为客户端发送的数据。
用户可使用一个客户端发送多条数据,亦可启动多个客户端向聊天室发送数据。启动位于不同主机上的多个客户端向聊天室中发送数据,聊天室中打印的信息如下:
-------UDP聊天室-------
172.16.43.31:50873 # 用户1
你好
172.16.43.33:64632 # 用户2
你们知道传智播客吗?
172.16.43.37:65200 # 用户3
知道
172.16.43.51:58017 # 用户4
知道
172.16.43.33:64632 # 用户2
那你们知道传智专修学院吗?
172.16.43.37:65200 # 用户3
那是什么?
172.16.43.51:58017 # 用户4
是传智播客创办的大学
观察打印结果,聊天室中接收并打印多个客户端发送的信息,可知UDP聊天室实现成功。
需要说明的是,在多台计算机中进行测试时,计算机中的防火墙可能会过滤掉来自其他主机的UDP客户端发送的数据包,为保证测试成功,可先使用“service iptables stop”命令关闭防火墙,测试完成后,再通过“service iptables start”命令重启防火墙。