[英]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.