当前位置: 首页 > 知识库问答 >
问题:

Python-Socket:如何在客户端同时实现recv()和send()

瞿宏儒
2023-03-14

我的环境:windows10和python 3.6

  1. 目的:我想建立一个在线聊天室,当客户端连接到服务器上,并向服务器发送消息时,服务器将向所有与它有联系的客户端广播消息。
  2. 关键点:所以有一个问题,我想让客户机监听服务器,同时等待输入。(代码发布在下面)
  3. 我的解决方案:当我试图通过python的线程来解决这个问题时,结果是,假设客户机A和客户机B都连接到服务器,并且客户机A发送多条消息,而客户机B只能接收第一条消息或者接收重复的、混乱的消息。(下面公布了大量错误)
  4. 代码解释为了防止我糟糕的开发技能使您感到困惑,我想对我的代码做一个简单的解释。
    1. 在发送每条消息之前,将首先发送消息的长度,因此recv端很容易确定应该分配多大的缓冲区。
    2. 所有这些“try”和“except”都用于使系统更健壮,以防意外断开连接
    3. 在服务器端,它接受连接请求,并通过线程处理每个连接。在每个线程中,如果消息是从客户端发送的,则服务器会将消息广播给其他客户端。
    4. 在客户端,我创建了一个线程来监听来自服务器的消息,并使用“input”保持等待输入。

    图像说明
    1。服务器在左侧窗口上运行,客户端A在右侧窗口上运行,客户端B在底部窗口上运行。
    2。具体操作为:客户端B发送“A B c d E”,客户端A接收“A”。客户端A发送了“A b c e D”,而客户端b收到了“[某些信息..]A\N[某些信息..]A”。
    3。我们可以从图像中了解到:当客户机在其他客户机发送任何消息之前发送多条消息时,那么其他客户机将只接收到客户机A发送的第一条消息,或者接收到重复的消息。

    最后,对不起我对套接字和线程的理解太差,解释太差。谢谢你帮忙。

    code for clinet:
    
    import socket
    import time
    import threading
    
    
    SERVER_HOST = "" # server ip
    LOCAL_HOST = "10.124.18.206"
    HOST = LOCAL_HOST
    
    HEADER = 64
    PORT = 42366
    CHECK_CLIENT = "!CHECK"
    FORMAT = "utf-8"
    DISCONNECT_MESSAGE = "!DISCONNECT"
    KEEP_MESSAGE = "KEEP"
    TIMEOUT = 50
    
    
    def gettimestamp():
        return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
    
    def send(msg):
        message = msg.encode(FORMAT)
        msg_length = len(message)
        send_length = str(msg_length).encode(FORMAT)
        send_length += b' ' * (HEADER-len(send_length))
        client.send(send_length)
        client.send(message)
    
    def recv():
        message = client.recv(HEADER)
        msg_length = len(message)
        message = message.decode(FORMAT)
        data = client.recv(msg_length).decode(FORMAT)
        return data
    
    def listen():
        while True:
            data = recv()
            if data:
                print(f"[MESSAGE {gettimestamp()}] {data}" )
            else:
                break
    
    def start():
        client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        print(f"[STARTING] Connecting to {HOST}:{PORT}")
        client.connect((HOST,PORT))
        send(CHECK_CLIENT)
        client_num = recv()
        print(f"There are {client_num} people in the chat.")
        print("Let's chat!")
        connected = True
        listen_th = threading.Thread(target=listen,args=())
        listen_th.daemon = True
        listen_th.start()
        while connected:
            time.sleep(0.3)
            data = input("[INPUT] ")
    
            try:
                send(data)
            except ConnectionAbortedError as e:
                connected = False
    
            if data == DISCONNECT_MESSAGE:
                connected = False
    
        print(f"[DISCONNECT {gettimestamp()}] {HOST}:{PORT}")
        client.close()
    
    if __name__ == "__main__":
        start()
    
    
    
    code for server
    
    # -*- coding: utf-8 -*-
    
    import socket
    import threading
    import time
    
    
    SERVER_HOST = "" # server ip
    LOCAL_HOST = "10.124.18.206"
    HOST = LOCAL_HOST
    
    PORT = 42366
    CHECK_CLIENT = "!CHECK"
    DISCONNECT_MESSAGE = "!DISCONNECT"
    HEADER = 64
    FORMAT = "utf-8"
    TIMEOUT = 60
    
    clients = []
    
    def gettimestamp():
        return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
    
    def send(conn,msg):
        try:
            message = msg.encode(FORMAT)
            msg_length = len(message)
            send_length = str(msg_length).encode(FORMAT)
            send_length += b' ' * (HEADER-len(send_length))
            conn.send(send_length)
            conn.send(message)
        except OSError as e:
            print(f"{e} in line 33")
            clients.remove(conn)
    
    def update_chat(msg,conn):
        global clients
        temp = []
        for client in clients:
            flag = 1
            if client != conn:
                try:
                    send(client,msg)
                except BrokenPipeError as e:
                    print(f"{e} in line 45")
                    flag = 0
                    continue
            if flag == 1:
                temp.append(conn)
    
        clients = temp
    
    
    def handle_client(addr,conn):
        print(f"[NEW CONNECTION {gettimestamp()}] {addr} connected.")
        print(f"[ACTIVE CONNECTIONS {gettimestamp()}] {threading.activeCount()-1}")
        connected = True
        clients.append(conn)
        while connected:
            try:
                conn.settimeout(TIMEOUT)
                msg_length = conn.recv(HEADER).decode(FORMAT)
                conn.settimeout(None)
                if msg_length:
                    msg_length = int(msg_length)
                    try:
                        msg = conn.recv(msg_length).decode(FORMAT)
                    except ConnectionResetError as e:
                        print(f"{e} in line 67")
                        connected = False
                    if msg == DISCONNECT_MESSAGE:
                        connected = False
                        clients.remove(conn)
                    elif msg == CHECK_CLIENT:
                        client_num = threading.activeCount()-1
                        send(conn,str(client_num))
                    else:
                        update_chat(f"{msg}",conn)
    
                    print(f"[{addr[0]+str(addr[1])} {gettimestamp()}] {msg}")
    
            except ConnectionResetError as e:
                print(f"{e} in line 81")
                connected = False
            except ConnectionAbortedError as e:
                print(f"{e} in line 84")
                continue
            except socket.timeout as e:
                connected = False
    
    
        print(f"[DISCONNECTED {gettimestamp()}] {addr}")
    
        conn.close()
    
    def start():
        print("[STARTING] Server is starting...")
        server = socket.socket()
        print(f"[BIDING] Binding address {HOST}:{PORT}")
        server.bind((HOST,PORT))
        server.listen()
        print(f"[LISTENING {gettimestamp()}] Server is listening on {HOST}:{PORT}")
        while True:
            conn,addr = server.accept()
            thread = threading.Thread(target=handle_client,args=(addr,conn))
            thread.daemon = True
            thread.start()
    
    if __name__ == "__main__":
        start()
    
    
    

共有1个答案

欧阳绪
2023-03-14
                msg = conn.recv(msg_length).decode(FORMAT)

这将最多接收msg_length字节。您需要确保正确接收msg_length字节。您可能希望编写一个receive all函数,该函数反复调用recv,直到准确地接收到所需的字节数。

 类似资料:
  • 本文向大家介绍Android socket实现原理详解 服务端和客户端如何搭建,包括了Android socket实现原理详解 服务端和客户端如何搭建的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android socket的实现原理,供大家参考,具体内容如下 Socket套接字 是网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。 socket实现的

  • 嗨,我的问题很简单: 我尝试通过TCP连接建立UDP连接(因为多个客户端通过多个通道连接到服务器,我想通过主TCP连接识别相同的客户端) 我通过在客户机上创建TCP和UDP套接字来实现这一点,并通过TCP将操作系统随机分配的本地UDP端口传输到服务器。(在Windows上,我通过getsocketname()获得sendto()之后的端口)。在服务器上,我使用这个端口将UDP数据包发送到这个客户机

  • 本文向大家介绍PHP基于socket实现客户端和服务端通讯功能,包括了PHP基于socket实现客户端和服务端通讯功能的使用技巧和注意事项,需要的朋友参考一下 本文主要介绍了PHP基于socket实现的简单客户端和服务端通讯功能,可实现服务端接收客户端发送的字符串进行翻转操作后返回客户端的功能,需要的朋友可以参考下 服务端: 客户端: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多

  • 本文向大家介绍python Socket之客户端和服务端握手详解,包括了python Socket之客户端和服务端握手详解的使用技巧和注意事项,需要的朋友参考一下 简单的学习下利用socket来建立客户端和服务端之间的连接并且发送数据 1. 客户端socketClient.py代码 2. 服务端serverSocket.py代码 3.操作过程 开两个控制台窗口,先运行服务端 python3 ser

  • 问题内容: 我尝试使用以下代码从服务器到客户端发送文件和目录列表。服务器正在从客户端接收消息,但我不知道服务器是否没有发送回结果或客户端是否不接受结果。 服务器端: 问题答案: 据我所见,您在客户端上做的同时在服务器上做。从服务器发送的字符串中没有行尾字符,因此客户端将永远无法完成。执行outqw.println()或添加到要发送的内容的末尾。话虽这么说,很难用一堆注释掉的东西来浏览未格式化的代码

  • TCPClient 和 UnixClient 这两个结构体包含 SocketClient 这个匿名字段,因此,SocketClient 上的字段和方法都会被继承。 ReadBuffer 字段 设置与连接相关的操作系统接收缓冲区的大小。当为 0 时,表示不进行设置,使用系统默认值。 WriteBuffer 字段 设置与连接相关的操作系统发送缓冲区的大小。当为 0 时,表示不进行设置,使用系统默认值。