在python中使用socket编程创建一个简易聊天室的数据传输问题?
题目描述
题目来源及自己的思路
抱歉,应该是基于UDP协议
创建客户端和服务端两端代码,实现收发信息代码完善后复制客户端代码副本即可
相关代码
粘贴代码文本(请勿用截图)服务端代码如下
# encoding=utf-8
import socket
import time
# 服务器的功能:收到信息后转发
def recv_send(server_ip, server_port):
# 创建套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 指明网络层和传输层的协议
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定服务器地址
s.bind((server_ip, server_port))
user_dict = {} # 保存用户名和其客户端地址
# 开始接收和发送数据
while True:
# 接收数据
recv_data, cli_addr = s.recvfrom(1024)
# 接收数据后解码并保存变量
recv_data = recv_data.decode('utf-8')
# 提取用户名和发送的信息并指定分割符
present_user, real_info = recv_data.split(':')
# if present_user in real_info and "欢迎" in real_info:
# user_dict[present_user] = cli_addr
# # 向其他客户端发送一个欢迎当前用户的信息
# for user, addr in user_dict.items():
# if user != present_user:
# send_data = f"server:欢迎{present_user}进入聊天室..."
# s.sendto(send_data.encode('utf-8'), addr)
# else:
# for user, addr in user_dict.items():
# if user != present_user:
# s.sendto(real_info.encode('utf-8'), addr)
# 判断用户是否是第一次进入聊天室
if present_user in real_info and "欢迎" in real_info:
user_dict[present_user] = cli_addr
# 向其他客户端发送一个欢迎当前用户的信息
send_data = f"server:欢迎{present_user}进入聊天室..."
else:
send_data = recv_data
# 判断用户是否退出
if real_info == 'exit': # 则从用户字典删除该用户
del user_dict[present_user]
send_data = f"server:{present_user}退出了聊天室..."
for user, addr in user_dict.items():
if user != present_user:
s.sendto(real_info.encode('utf-8'), addr)
# 显示收到的信息
print(f"{present_user} {time.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" {real_info}")
def main():
server_ip = '127.0.0.1'
server_port = 6666
recv_send(server_ip, server_port)
if __name__ == '__main__':
main()
客户端代码如下
# encoding=utf-8
import socket
import threading
import time
# 发送数据函数
def send(socket_obj, server_addr, client_user):
while True:
send_data = input("服务器已启动:")
send_data = f"{client_user}:{send_data}"
socket_obj.sendto(send_data.encode('utf-8'), server_addr)
if send_data == 'exit':
break
# 接收数据函数
def recv(socket_obj):
while True:
try:
recv_data, addr = socket_obj.recvfrom(1024)
except:
break
recv_data, addr = socket_obj.recvfrom(1024)
recv_data = recv_data.decode('utf-8')
user_name, real_data = recv_data.split(":")
# 显示收到的信息
print(f"{user_name} {time.strftime('%Y-%m-%d %H:%M:%S')}")
print(f" {real_data}")
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 指明网络层和传输层的协议
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 设置服务器ip和端口号
sever_ip = '127.0.0.1'
server_port = 6666
server_addr = (sever_ip, server_port)
# 给客户端设置用户名
user_name = '张三'
# 第一次进入聊天室,发送一个欢迎信息,让服务器知道用户的地址
send_info = f"{user_name}:欢迎{user_name}进入聊天室..."
s.sendto(send_info.encode('utf-8'), server_addr)
# (1)创建两个线程,一个发送数据,一个接收数据
a_send = threading.Thread(target=send, args=(s, server_addr, user_name))
a_recv = threading.Thread(target=recv, args=(s,))
# 启动线程
a_send.start()
a_recv.start()
a_send.join() # 等待发送线程结束
# 关闭套接字对象
s.close()
if __name__ == '__main__':
main()
你期待的结果是什么?实际看到的错误信息又是什么?
实际错误信息如下但问题是,若两个客户端为同一user_name此时可以正常通信如下图,但两个客户端若为不同user_name则某一客户端会出现第一张图的错误,恳请大佬解惑!
回复
1个回答
test
2024-07-08
俩问题。
- 发送时数据格式问题
for user, addr in user_dict.items():
if user != present_user:
# FIXME: 这块应该是 --> "用户名:消息" <--
s.sendto(real_info.encode('utf-8'), addr)
- 接收数据时
# 接收数据函数
def recv(socket_obj):
while True:
try:
# FIXME: 这里接收的数据直接忽略了?
recv_data, addr = socket_obj.recvfrom(1024)
except:
break
# 这边接收的话,会丢失数据
recv_data, addr = socket_obj.recvfrom(1024)
本文参与了SegmentFault 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容