1.UDP是无连接的,但是不代表客户端的socket每次发送之后都要销毁!一开始只有服务端的socket在一直使用,客户端的socket每次创建后发送一次就销毁,以至于无法判断用户的身份。socket不重建,用户的ip地址和端口号就不会改变,可以通过记录ip地址和端口号来记录用户的身份。 2.UDP的服务端一直循环等待接收消息,客户端一直等待用户输入 。 3.由于UDP的无连接特性,服务端和客户端是相对的,服务端和客户端都需要监听。那么客户端可能需要多线程,一个线程用于等待用户输入,一个线程用于监听服务端。
多线程示例:
https://www.runoob.com/python3/python3-multithreading.html
Server端
总之比client端简单多了
Client端
1.必须多线程 2.一个线程(主线程)用于等待键盘输入,一个线程(子线程)用于接收服务端的信息。 3.用于接收服务端信息的子线程,每次接收到信息之后打印在屏幕上 问题:需要通过server端返回的信息判断是否登录成功。如何将子线程接到的server端返回消息传递给主线程? 方法:在发送login信息(或者其他需要等待服务端回复的信息)之后,阻塞主线程,直到子线程接到服务端的回信 问题:子线程循环抢占锁,主线程只有发送login之类的信息才会抢占锁。如果子线程连续抢占了锁就会导致程序死锁,主线程等待子线程释放,子线程等待服务端信息。必须避免。 方法:将所有返回信息的处理放在子线程中。为了区分 阶段总结:发送消息一共有2种情况:1.server端主动向client端发送,例如在公聊或者私聊的时候,对方发送了消息。由于这部分不需要等待用户输入,可能放在子线程中处理和打印。2.client端向server端发送消息,并且等待回应,收到回应后进行处理并显示给用户。 只能选择将大部分信息设为全局变量,然后在子线程中处理服务器返回的信息。
# 错误写法:
while True:
lock.acquire() # 启动锁,在接收到数据之前,不允许其他人访问
data, address = sock.recvfrom(MAX_BYTES)
text = data.decode('ascii')
print('The server {} replied {!r}'.format(address,text))
text_rtn = text
lock.release() # 释放锁,允许其他访问
4.为了测试,需要在我的电脑上运行多个client端和一个server端。每个client端都需要bind本机的端口。这样,就需要在每次创建client端的时候,手动输入client的端口号。
5.正在进行:准备删除在输入前显示用户名的功能,改为经常性的cls,以保持基本信息的显示。可以在cls之后将基本信息显示在cmd的最上端
|