如果收到特定字符串,如何退出while循环?

时间:2017-07-03 14:54:54

标签: python sockets

我的查询是关于我已经将树莓派作为服务器而我需要通过另一个使用套接字的设备来控制pi的gpio。我的服务器代码就是当我发送字符串' on&#39时通过客户端,LED必须开启,关闭,闪烁,然后通过客户端关闭。尽管led开/关/闪烁都是成功的,但我在led闪烁期间面临问题。如果客户端在LED闪烁操作期间打开/关闭字符串,那么led的开/关操作是不成功的。那我该怎么做呢? 任何帮助表示赞赏。

# server code
import socket
import time
import sys
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(12,GPIO.OUT)
GPIO.output(12,False)

ms=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ms.bind(('',1234))
ms.listen(1)
conn,addr=ms.accept()

print('Connection Established from ',addr)
while True:
    data=conn.recv(1000)
    print(addr,': ',data)
    if not data:
        break

    elif data==b'raspberry\n':
        print('Hello Pi')

    elif data==b'on\n':
        print('led is turned ON')
        GPIO.output(12,True)

    elif data==b'off\n':
        print('led is turned OFF')
        GPIO.output(12,False)

    elif data==b'blink\n':
        print('led blinking')

        while True:                       #.... Here Is my query....
            GPIO.output(12,True)
            time.sleep(0.5)
            GPIO.output(12,False)
            time.sleep(0.5)

            if conn.recv(1000)==b'on\n' or conn.recv(1000)==b'off\n':  
                break

    elif data==b'exit\n':
        print('Goodbye..')
        time.sleep(1.5)
        break

conn.close()
ms.close()
sys.exit()

1 个答案:

答案 0 :(得分:1)

问题是您使用收到的数据,但不将其存储在data中。

您需要将收到的数据存储在data

while True:
    GPIO.output(12,True)
    time.sleep(0.5)
    GPIO.output(12,False)
    time.sleep(0.5)

    data = conn.recv(1000)
    if data==b'on\n' or data==b'off\n':  
        break

但是,data将在下一次迭代时被data = conn.recv(1000)覆盖。 因此,您需要在此时响应开/关指令。

while True:
    GPIO.output(12,True)
    time.sleep(0.5)
    GPIO.output(12,False)
    time.sleep(0.5)

    data = conn.recv(1000)
    if data==b'on\n':
        #on
        break
    elif data==b'off\n':
        #off
        break

正如您所要求的,这是一种处理网络应用程序的简单方法。

首先,有一个接收消息的线程。

import threading
import queue

class Receiver(threading.Thread):
    def __init__(self, connection):
        super().__init__()
        self.connection = connection
        self.messages = queue.Queue()

    def run(self):
        while True:
            message = self.connection.recv(1000)
            self.queue.put(message)

    def get_message(self):
        if not self.queue.empty():
            return self.queue.get()
        else:
            return None

然后,在主循环中,不要等待来自conn的消息,而是使用Receiver对象的队列。

receiver = Receiver(conn)    # conn is the connection object returned by ms.accept()
receiver.start()

while True:
    message = receiver.get_message()
    if message is not None:
        process_message(message)

好的,所以这里有很多事情,但实际上并不那么难。 首先,我定义了一个Receiver类,它扩展了threading.Thread,并覆盖了__init__run__init__方法用于设置允许获取消息的属性,run方法描述线程将执行的操作。 该线程将运行一个永久while循环,在该循环中,它将从网络接收消息,并将它们放入队列中。

顺便说一句,queue模块给出了同步队列,其中包括Queue。 在线程上下文中使用这些而不是列表是个好主意。 此外,从Queue对象获取对象并不是那么简单,因此我在get_message类中定义了Receiver方法,这将为我完成工作。

然后我通过传递从Receiver收到的conn对象来实例化ms.accept类,然后开始我的线程。 最后,我运行我的主while循环,在其中我使用来自接收者队列的消息。

那么它有什么变化?

接收方法(此处为conn.recv)是阻塞的,这意味着它们会停止其线程的执行流程。 通过将它们放在自己的线程中,主线程将不会被暂停。 通过Queue对象,主线程可以从接收线程获取数据,但不会被阻止。 如果有数据,则需要它。如果没有,它就会继续。