我正在尝试从服务器发送和接收数据。当我从eclipse或python IDLE运行下面的python程序时,我从服务器得到响应。但是,当我从Raspberry Pi运行程序时,出现错误。下面是简单的代码和错误。
import socket,time
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = '127.0.0.1'
port = 1883
address = (ip,port)
client.connect(address)
print("connected")
def close():
global client
client.close()
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(address)
while 1:
client.send(b'\x01\x04\x00\x00\xxxxxx')
print("sent")
try:
raw_data = client.recv(1024)
except:
close()
raw_data = client.recv(1024)
received_data = " ".join("{:02x}".format(byte) for byte in
(raw_data))
print(received_data)
time.sleep(1)
在树莓派中运行此代码时,出现BrokenPipe错误。为什么在树莓派中会发生这种情况?
错误:
connected
sent
received
sent
Traceback (most recent call last):
File "exdu.py", line 18, in <module>
client.send(b'\x01\x04\x00\x00\xxxxxxxxx')
socket.error: [Errno 32] Broken pipe
答案 0 :(得分:0)
当管道(在本例中为TCP套接字)被另一侧意外关闭并且recv
返回空响应或send
试图写入关闭的连接时,会导致管道损坏
有很多不太理想的代码可能会导致代码中的管道错误。
我将尝试通过注释指出一些让我脱颖而出的事情:
import socket,time
# it would be nice to have a function wrapping this but as it is this is not the issue.
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = '127.0.0.1'
port = 1883
address = (ip,port)
client.connect(address)
print("connected")
def close():
global client
# If you read the python socket documentation https://docs.python.org/2/howto/sockets.html
# you will see that they advise sending a shutdown packet to the other side of the connection.
# In my experience this is actually extremely important when properly handling TCP connections and may be causing this issue.
# you must do this from the side that closes the connection, this includes when the server closes a connection.
client.shutdown(SHUT_RDWR) # this is what you want to do here.
client.close()
# connecting to a new socket here makes no sense and may also cause an issue.
client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(address)
raw_data=client.recv(1024)
while 1:
client.send(b'\x01\x04\x00\x00\xxxxxx')
print("sent")
try:
raw_data = client.recv(1024)
except:
# this except statement may cause an exception itself.
# Not only that but you are probably getting your broken pipe error
# here from the recv in close().
close()
raw_data = client.recv(1024)
received_data = " ".join("{:02x}".format(byte) for byte in
(raw_data))
print(received_data)
time.sleep(1)
为代码注释道歉,但是当您尝试使用一种解决方案时,我发现当片段复制粘贴时它们很有用。
作为扩展,我将编写代码,您必须更像python docs示例:
class mysocket:
def __init__(self, sock=None):
if sock is None:
self.sock = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
else:
self.sock = sock
def connect(self, host, port):
self.sock.connect((host, port))
# important bit of missing code
def disconnect(self):
self.sock.shutdown(SHUT_RDWR)
self.sock.close()
def mysend(self, msg):
totalsent = 0
while totalsent < MSGLEN:
sent = self.sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def myreceive(self):
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN:
chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
if chunk == '':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return ''.join(chunks)
您可以重写发送和接收功能以进行出价,然后像这样调用它:
socket = mysocket()
socket.connect('127.0.0.1', 1883)
try:
socket.mysend(b'\x01\x04\x00\x00\xxxxxx')
raw_data = socket.myrecieve()
# do more stuff
except:
socket.disconnect()
这是示例代码,但可能会让您走上正确的道路。
答案 1 :(得分:-1)
管道破损意味着没有完全按照您的要求进行。您确定服务器在localhost
的树莓派上正常运行吗?
否则,您可能要单独运行服务器(也许是heroku或digitalocean是相关的)或检查pi的防火墙(我非常怀疑这是localhost-> localhost连接的问题)