在python中使用socket编程创建一个简易聊天室的数据传输问题?

作者站长头像
站长
· 阅读数 6

题目描述

在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()

你期待的结果是什么?实际看到的错误信息又是什么?

实际错误信息如下在python中使用socket编程创建一个简易聊天室的数据传输问题?但问题是,若两个客户端为同一user_name此时可以正常通信如下图,但两个客户端若为不同user_name则某一客户端会出现第一张图的错误,恳请大佬解惑!在python中使用socket编程创建一个简易聊天室的数据传输问题?

回复
1个回答
avatar
test
2024-07-08

俩问题。

  1. 发送时数据格式问题
        for user, addr in user_dict.items():
            if user != present_user:
                # FIXME: 这块应该是 --> "用户名:消息" <--
                s.sendto(real_info.encode('utf-8'), addr)
  1. 接收数据时
# 接收数据函数
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 思否面试闯关挑战赛,欢迎正在阅读的你也加入。
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容