简体   繁体   English

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

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

I've made a socket where i need to stream some stdout data from a C file to my computer over ethernet.我已经制作了一个套接字,我需要将 C 文件中的一些标准输出数据通过以太网传输到我的计算机。 It works fine until i close the connection at client side where i then get the following error at the server socket:它工作正常,直到我关闭客户端的连接,然后我在服务器套接字上收到以下错误:

    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

I would like the socket to go back to accept new connections when the client closes the connection.我希望 go 的套接字在客户端关闭连接时重新接受新连接。 I've tried to read the python socket documentation but can't find anything about the issue.我尝试阅读 python 套接字文档,但找不到任何关于该问题的信息。 I could send a "quit" message to the server - but i would rather that the server just ignores the pipe is closed and goes back to accepting new connections.我可以向服务器发送“退出”消息 - 但我宁愿服务器忽略 pipe 已关闭并返回接受新连接。

I have my server code (i get the error on the server. I've outlined the issue by wrapping it in ## ISSUE IS HERE ##):我有我的服务器代码(我在服务器上收到错误。我已通过将其包装在 ## 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()

And my client code:我的客户代码:

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 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

I solved the issue by just adding a try/except with BrokenPipeError to wrap the makefile write method.我通过使用 BrokenPipeError 添加 try/except 来包装 makefile 写入方法解决了这个问题。 For anyone in the future here is the code that solved the brokepipe issue:对于未来的任何人来说,这里是解决故障管道问题的代码:

  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.

相关问题 conn.send(&#39;Hi&#39;.encode()) BrokenPipeError: [Errno 32] Broken pipe (SOCKET) - conn.send('Hi'.encode()) BrokenPipeError: [Errno 32] Broken pipe (SOCKET) 获取 BrokenPipeError:[Errno 32] 发送第二个套接字 MSG 时损坏 pipe - Getting BrokenPipeError: [Errno 32] Broken pipe When Sending Second Socket MSG BrokenPipeError: [Errno 32] 运行 GAN 时管道损坏错误 - BrokenPipeError: [Errno 32] Broken pipe error when running GANs 已解决:Python 多处理 imap BrokenPipeError: [Errno 32] Broken pipe pdftoppm - Solved: Python multiprocessing imap BrokenPipeError: [Errno 32] Broken pipe pdftoppm 我得到 BrokenPipeError: [Errno 32] Broken pipe 错误 python - I get BrokenPipeError: [Errno 32] Broken pipe error in python Python socket errno 32 断管 - Python socket errno 32 broken pipe socket.error:[Errno 32]管道破裂 - socket.error: [Errno 32] Broken pipe Matlab 服务器与树莓派上的 python 客户端 BrokenPipeError: [Errno 32] Broken pipe - Matlab Server with python client on raspberry pi BrokenPipeError: [Errno 32] Broken pipe Errno 32:管道损坏 - Errno 32: Broken pipe Paho MQTT “无法在套接字上接收:[Errno 32] Broken pipe” - Paho MQTT “failed to receive on socket: [Errno 32] Broken pipe”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM