套接字是全双工,所以我们只需要使用一个套接字,使用两个子线程来接收和发送消息便可以了。

当然,如果要两个都能收消息,我们需要都绑定端口。

下面给出代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import threading
import socket


def recv_msg(udp_socket):
"""接收数据"""
while True:
recv_data = udp_socket.recvfrom(1024)
# print(recv_data)
print("%s:%s" % (str(recv_data[1]), recv_data[0].decode('gbk'))) # 1. 接收是解码需要decode,而不是encode 2. 注意 str 的括号

def send_msg(udp_socket, dest_ip, dest_port):
"""发送数据"""
while True:
send_data = input('输入要发送的数据:')
udp_socket.sendto(send_data.encode('gbk'), (dest_ip, dest_port))


def main():
''' 完成 udp 聊天器的整体控制'''

# 1. 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 2. 绑定本地信息
udp_socket.bind(('', 7890))

# 3. 获取对方的 ip 与 port
dest_ip = input('请输入对方的 ip: ')
dest_port = int(input('请输入对方的 port:'))

# 4. 创建两个线程,去执行相应的功能
t_recv = threading.Thread(target=recv_msg, args=(udp_socket, ))
t_send = threading.Thread(target=send_msg, args=(udp_socket, dest_ip, dest_port))

t_recv.start()
t_send.start()

udp_socket.close()

if __name__ == '__main__':
main()

简单讲解:

因为我们要接收信息,所以需要绑定一下端口。

将收消息和发消息分别放到两个线程中,分别执行对应功能

注意:

收消息,要将收到的 bytes 解码(decode)为对应平台的编码

发消息,要将消息编码(encode)为 bytes,然后在发送。

我使用的都是 Windows 平台,所以编解码都是用 GBK

收发数据条数不固定,使用 while True

Thread 的 args 参数的传递(元组)