python3 - 使用socket.send()时出现管道错误

时间:2015-05-27 06:05:10

标签: python sockets python-3.x

我正在编写客户端 - 服务器即时消息程序。我在Python 2中创建了一个类似的程序,我正在尝试用Python 3编程。问题是当服务器接收消息并尝试将其发送到另一个客户端时,它给了我“[Errno 32] Broken Pipe”和退出。

我做了一些研究,发现当客户端断开连接时会发生这种情况,所以我做了一些测试,但是在客户端断开连接时无法找到。 (我使用的是Ubuntu 14.04和Python 3.4)

这是服务器代码:

unsigned

客户端代码:

import socket, select, sys

def broadcast(sock, messaged):
    for socket in connection_list:
        if socket != s and socket != sock:
        # Here is where it gives me the broken pipe error
            try:
                s.send(messaged.encode("utf-8"))
            except BrokenPipeError as e:
                print(e)
                sys.exit()
connection_list = []
host = ''
port = 5558

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host,port))
s.listen(5)

connection_list.append(s)
read_sockets,write_sockets,error_sockets = select.select(connection_list,[],[])
while True:
    for sock in read_sockets:
        if sock == s:
            conn, addr = s.accept()
            connection_list.append(conn)
            client = "Client (%s,%s) connected" % addr
            print(client)
            broadcast(sock,client)

        else:
            try:
                data = sock.recv(2048)
                decodeddata = data.decode("utf-8")
                if data:
                    broadcast(sock, decodeddata)
            except:
                offline = "Client " + addr + "is offline"
                broadcast(sock, offline)
                print(offline)
                connection_list.remove(sock)
                sock.close()
                continue

1 个答案:

答案 0 :(得分:1)

要完成这项工作,您必须解决两个问题。

首先,在客户端和服务器端,你必须将CordovaWebView 放在循环中,而不是在外面。否则,如果在你进入循环之前有什么需要阅读的话,你会一遍又一遍地回忆,如果没有,你就永远不会回忆。解决这个问题后,您可以摆脱select。 (你应该从不需要一个time.sleep(1)来解决这样的问题;充其量它会掩盖问题,并且通常会引入新问题。)

同时,在服务器端sleep内,您正在执行broadcast。但s.send是您的侦听器套接字,而不是连接的客户端套接字。您需要s,因为socket.sendsocket中的每个套接字。

您的代码中也存在许多无关的问题。例如:

  • 我不确定客户端中的connection_list假设要捕获的内容。它主要似乎捕获的是,大约50%的时间,命中^ C结束程序会触发发送提示。但是,当然,就像任何裸except:一样,它也会掩盖代码中的任何其他问题。
  • 除了" connected"之外,没有办法来回发送任何数据。除了except:子句之外的消息。
  • except:是主机和端口的元组,因此当有人离线时,服务器会因尝试格式化离线消息而引发addr
  • TypeError始终是最后连接的客户,而不是断开连接的客户。
  • 您未将套接字设置为非阻塞模式。
  • 您未在addr上查看EOF。这意味着在您收到错误之前,您实际上并未检测到客户端已脱机。这通常只有在您尝试recv他们发送消息后才会发生(例如,因为其他人已连接或断开连接)。