Python 从raspberry pi发出请求时未收到套接字数据
我正在尝试从服务器发送和接收数据。当我从eclipse或pythonidle运行下面的python程序时,我从服务器得到响应。但是,当我从Raspberry Pi运行程序时,我得到了一个错误。下面是简单的代码和错误Python 从raspberry pi发出请求时未收到套接字数据,python,raspberry-pi,Python,Raspberry Pi,我正在尝试从服务器发送和接收数据。当我从eclipse或pythonidle运行下面的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(
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)
当我在raspberry pi中运行这段代码时,我得到了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
已连接
发送
收到
发送
回溯(最近一次呼叫最后一次):
文件“exdu.py”,第18行,在
client.send(b'\x01\x04\x00\x00\xxxxxxxxx')
socket.error:[Errno 32]管道破裂
管道破裂意味着某些东西并没有完全按照您希望的方式通过。您确定服务器在本地主机上的raspberry pi上正确运行吗
否则,您可能需要单独运行服务器(可能与heroku或digitalocean有关),或者检查pi的防火墙(我非常怀疑这是localhost->localhost连接的问题)当管道(在本例中是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文档示例:
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)
这是示例代码,但可能会将您设置在正确的路径上。您正在尝试从客户端接收内容(try block),如果失败(block除外),您将再次尝试。如果它在块中失败怎么办?您不再捕获该异常。如果您有套接字错误异常,我没有将其添加到此代码中。但是,上面的代码用于在pythonidle中执行时获取响应,我不确定raspberry pi.Post的实际情况。在哪一行引发异常?还要捕获并打印
except:
子句中的异常。在失败的情况下,数据是否成功地从客户端发送,您能否确认服务器是否接收到数据?断开的管道通常意味着写入已关闭的连接,因此服务器正在关闭连接。。。回溯有助于找出发生这种情况的地点和原因。我看到您正在设置客户端以连接到本地计算机上的服务器。这可能是一个愚蠢的问题,但当您尝试在RasPi上执行此脚本时,服务器(假设MQTT,基于端口号)是否确实在RasPi上运行(或者,是否相应地替换脚本中的ip
)@mhawke,我在与断管相关的其他帖子上尝试了您的解决方案之一,我也犯了同样的错误。请参考更新的问题。但无法找到解决方案我的服务器在其他地方,我正在尝试使用我机器中的客户端程序(即raspberry pi)连接我的服务器。我确信我的服务器正在按预期运行。否则,当我在本地机器上以pythonidle运行程序时,我将不会收到响应。
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()