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(

我正在尝试从服务器发送和接收数据。当我从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(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()