Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python3-使用socket.send()时发生断管错误_Python_Sockets_Python 3.x - Fatal编程技术网

python3-使用socket.send()时发生断管错误

python3-使用socket.send()时发生断管错误,python,sockets,python-3.x,Python,Sockets,Python 3.x,我正在编写一个客户机-服务器即时消息程序。我在Python2中创建了一个类似的程序,并尝试在Python3中编程。问题是,当服务器接收消息并尝试将其发送到另一个客户端时,它会给我“[Errno 32]断管”并退出 我做了一些研究,发现当客户端断开连接时会发生这种情况,所以我做了更多的测试,但没有找到客户端断开连接的时间。(我正在使用Ubuntu 14.04和Python 3.4) 以下是服务器代码: import socket, select, sys def broadcast(sock,

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

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

以下是服务器代码:

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
和客户端代码:

import socket, select, string, sys, time

def prompt(data) :
     print("<You> " + data)
def Person(data) :
    print("<Receiver> " + data)

if __name__ == "__main__":

    host = "localhost"
    port = 5558

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(2)

    try:
        s.connect((host,port))
    except:
        print('Unable to connect')
        sys.exit()
    print('Connected.')
    socket_list = [s]
    read_sockets,write_sockets,error_sockets = select.select(socket_list,[],[])
    while 1:
        for sock in read_sockets:
            if sock == s:
                try:
                    time.sleep(1)
                    data = sock.recv(1024)             
                    Person(data.decode("utf-8"))
                except:
                    msg = input("Send a message: ")
                    try:
                        s.send(str.encode(msg))
                    except:
                        print("Server is offline")
                        sys.exit()


            else:
                print("Server is offline")
                sys.exit()
导入套接字、选择、字符串、系统、时间
def提示符(数据):
打印(“+”数据)
def人员(数据):
打印(“+”数据)
如果名称=“\uuuuu main\uuuuuuuu”:
host=“localhost”
端口=5558
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s、 设置超时(2)
尝试:
s、 连接((主机、端口))
除:
打印('无法连接')
sys.exit()
打印('已连接')
套接字\u列表=[s]
读插槽,写插槽,错误插槽=选择。选择(插槽列表,[],[])
而1:
对于插入式读_插槽:
如果sock==s:
尝试:
时间。睡眠(1)
数据=sock.recv(1024)
人员(数据解码(“utf-8”))
除:
msg=输入(“发送消息:”)
尝试:
s、 发送(str.encode(msg))
除:
打印(“服务器脱机”)
sys.exit()
其他:
打印(“服务器脱机”)
sys.exit()

要使其正常工作,您必须解决两个问题

首先,在客户端和服务器端,必须将
select
放在循环内部,而不是外部。否则,如果在你进入循环之前有一些东西要读,你会一遍又一遍地记录,如果没有,你永远不会记录。一旦你解决了这个问题,你就可以摆脱时间。睡眠(1)。(解决这样的问题永远不需要
睡眠
;它最多只能掩盖问题,通常会引入新问题。)

同时,在服务器端,在
广播
内部,您正在执行
s.send
。但是
s
是您的侦听器套接字,而不是连接的客户端套接字。您需要
socket.send
,因为
socket
connection\u列表中的每个套接字


代码中也有许多不相关的问题。例如:

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

  • 您正在实施应用程序吗?供将来参考:您需要在普通文本和缩进代码之间留一个空行,或者代码的格式不是代码。我为您解决了这个问题。一个明显的问题是,您没有在循环中调用
    select
    ,您只调用了一次,然后假设由于套接字只可读一次,所以它将永远可读。通常,使用bare
    except:
    子句会使代码很难调试,因为你看不到实际的异常发生。例如,当您进入服务器中的“脱机”代码时,并不总是因为客户端断开了连接,而是因为您忽略了实际的异常,所以无法判断。