繁体   English   中英

BrokenPipeError:[Errno 32] makefile 插座的 pipe 损坏?

[英]BrokenPipeError: [Errno 32] Broken pipe for makefile socket?

我已经制作了一个套接字,我需要将 C 文件中的一些标准输出数据通过以太网传输到我的计算机。 它工作正常,直到我关闭客户端的连接,然后我在服务器套接字上收到以下错误:

    Traceback (most recent call last):
  File "/home/pi/Documents/av/network/server_socket.py", line 82, in <module>
    main()
  File "/home/pi/Documents/av/network/server_socket.py", line 67, in main
    sf.write(line.rstrip())
  File "/usr/lib/python3.9/socket.py", line 722, in write
    return self._sock.send(b)
BrokenPipeError: [Errno 32] Broken pipe

我希望 go 的套接字在客户端关闭连接时重新接受新连接。 我尝试阅读 python 套接字文档,但找不到任何关于该问题的信息。 我可以向服务器发送“退出”消息 - 但我宁愿服务器忽略 pipe 已关闭并返回接受新连接。

我有我的服务器代码(我在服务器上收到错误。我已通过将其包装在 ## ISSUE IS HERE ## 中来概述问题):

import socket
import time
import os
import subprocess

# start server and wait for connections
def startServerSocket(PORT):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    sock.bind(('', PORT)) # bind loopback addr
    sock.listen(2)
    
    return sock

# initiate the ethernet protocol and log client to /var/log/pythonconnection.log
def readyConnection(conn, addr):
    # send request to get incoming connection host name        
    data = "whoisthis".encode()
    conn.sendall(data)

    # await with blocking recv for client response and log response
    data = conn.recv(1024)

    # need to be logged
    print("\nConnected to " , data.decode(), " as ", addr[0], " at [", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), "]")


    # tell that we're ready to start stream
    data = "ready".encode()
    conn.sendall(data)

    # get response saying client is ready to rec
    data = conn.recv(1024)
    if (data.decode()=="ready"):
        return True

    
    return False

        

def main():
    sock = startServerSocket(4000)
    print("waiting for connection... ")
  

    while True:
        conn, addr = sock.accept()

        # create serverfile to transmit IO signals to client via stream
        sf = conn.makefile("wrb", buffering=0)  
 
        # connection function
        connection = readyConnection(conn, addr)

        if (connection):
            print("[0/2] -> Valid connection established")
            print("[1/2] -> Printing stream to socket")
            
            # start reading from stdout in subprocess

            proc = subprocess.Popen(
                        ["/home/pi/Documents/av/sonar/a.out"],stdout=subprocess.PIPE)

            while True:
                line = proc.stdout.readline() # read one stdout line
                if not line:
                    break

                ## ISSUE IS HERE ##############
                sf.write(line.rstrip()) # write line to socket file
                ## ISSUE IS HERE ##############

                sf.flush() # force line to be sent immediately
            

        sf.close()
        conn.close()
        print("[x/x] -> Client has closed connection or stream reached EOF")
            






if __name__ == '__main__':
    main()

我的客户代码:

import socket
import time;

# function to setup and try to connect to a server
def connect(HOST, PORT):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
    sock.connect((HOST, PORT)) # raspberry pi addr + allowed port
    
    return sock


def handleRequest(data):
    output = ""
    if (data=="whoisthis"):
        output = socket.gethostname()
        print("-> Connecting as ", output)
    
    if (data=="ready"):
        print("-> Socket ready for IO")
        output = "ready" 
    
    return output
    


def main():

    sock = connect('123.123.1.69', 4000)
    cf = sock.makefile("wrb", buffering=0)

    while True:
        data = sock.recv(40).decode()
        handler = handleRequest(data)

        print(data.strip()+"\n")
        if (handler.strip() != ""):
            if (data.strip()=="ready"):
                sock.sendall("ready".encode()) # tell we're also ready to stream
                break ## exit loop
            
            sock.sendall(handler.encode())
        time.sleep(0.1) # just sleep while testing 

    # ready to recieve stream via ethernet
    print("-> ready to stream")
    while True:
        print(cf.read(64).decode()) # read 64 bytes at a time
        time.sleep(0.1)

if __name__ == '__main__':
    main()

Edit: I've also tried the select library for I/O based on https://docs.python.org/3/library/select.html where i just copied some code from https://stackoverflow.com/a/ 21802953/15386210

我通过使用 BrokenPipeError 添加 try/except 来包装 makefile 写入方法解决了这个问题。 对于未来的任何人来说,这里是解决故障管道问题的代码:

  proc = subprocess.Popen(
                    ["/home/pi/Documents/av/sonar/a.out"],stdout=subprocess.PIPE)

        while True:
            line = proc.stdout.readline() # read one stdout line
            if not line:
                break
            try:
                sf.write(line.rstrip()) # write line to socket file
            except (BrokenPipeError, IOError):
                print("an errror aka client disconnect")
                break
            sf.flush() # force line to be sent immediately
        

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM