从树莓派发出请求时未收到套接字数据

时间:2018-12-05 10:00:40

标签: python raspberry-pi

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

2 个答案:

答案 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连接的问题)