Python:在等待服务器套接字连接时运行循环

0 投票
1 回答
1963 浏览
提问于 2025-04-18 17:40

我有一个液晶显示屏,用来显示我在XBMC上观看电影的时间码。我希望在没有播放内容的时候,能显示当前的日期和时间。这个液晶显示屏是通过一个运行Python的TCPSocketServer服务器来工作的,它接收来自我XBMC安装的文本信息。问题是,我必须保持一个活跃的网络连接,这样XBMC才能通过这个连接发送时间和日期,液晶显示屏才能显示出来。

我觉得最好的办法是先显示液晶显示屏所在机器的日期,然后在连接活跃时切换到“时间码视图”。

有没有什么“Python风格”的方法,可以设置一个TCPSocketServer,让它在等待连接时循环显示日期,然后在接收到数据时改变行为来处理这些数据?

非常感谢!

1 个回答

0

这里有段代码可以实现你想要的功能。它启动了一个TCP服务器,监听发送到9876端口的文本。当收到文本时,它会把这些文本发送给显示对象。同时,代码还设置了一个定时器,每秒运行一次,向显示对象发送“闲置文本”(也就是当前的时间戳)。

显示对象会接收到来自服务器的正常更新文本,以及来自第二个线程的“闲置文本”。这个对象知道自从上次收到真实文本已经过了多久,因此会显示这两种消息中的一种。

如果显示对象连接到了硬件,它可以使用 multiprocessing.RLock 或其他机制来保护自己。

祝你玩得开心!

lcdcontrol.py 源代码

import signal, SocketServer, threading, time

class Display(object):
    IDLE_TIME = 5               # seconds

    def __init__(self):
        self.updated = None
        self.write('Hello')

    def _write(self, arg):
        print 'DISPLAY:', arg

    def write(self, arg):
        """
        update display and 'last updated' timestamp
        """
        self._write(arg)
        self.updated = time.time()

    def idle(self, arg):
        """
        update display only if it's been a few seconds
        """
        if time.time() - self.updated >= self.IDLE_TIME:
            self._write(arg)

class DisplayHandler(SocketServer.BaseRequestHandler):

    DisplayObj = None          # class var

    def handle(self):
        text = self.request.recv(1024).strip()
        print "{} wrote: {}".format(
            self.client_address[0], text,
            )
        # send text to LCD immediately
        self.DisplayObj.write(text)


def check_idle(display_obj):
    """
    update display with current time if it's idle
    """
    while True:
        display_obj.idle(
            time.strftime('time: %H:%M:%S'),
        )
        time.sleep(1)


def start_server(host, port):
    """
    start (single threaded) server
    """
    SocketServer.TCPServer(
        (host, port), 
        DisplayHandler,
    ).serve_forever()


def main(host, port):
    display = Display()

    # store global display obj so Handler can get to it
    DisplayHandler.DisplayObj = display

    print 'serving on {}:{}'.format(host, port)
    print 'Example: echo beer | nc localhost {}'.format(port)
    print

    server_t = threading.Thread(
        target=start_server, args=(host, port)
    )
    server_t.daemon = True
    server_t.start()

    idle_t = threading.Thread(
        target=check_idle, args=[display],
        )
    idle_t.daemon = True
    idle_t.start()

    # wait for control-C to interrupt
    try:
        signal.pause()
    except KeyboardInterrupt:
        pass

if __name__ == "__main__":
    main("localhost", 9876)

示例运行

在这里,我启动了服务器,等了几秒钟,然后输入了 fortune -s | nc localhost 9876 来给我的LCD服务器发送一条简短的幸运语。

注意“闲置计时器”在 :07 停止,输出了幸运语,等了五秒钟,然后继续显示 :13:14。这个消息显示了五秒钟后又切换回闲置时间戳。

python ./lcdcontrol.py
DISPLAY: Hello
serving on localhost:9876
Example: echo beer | nc localhost 9876

DISPLAY: time: 13:08:06
DISPLAY: time: 13:08:07
127.0.0.1 wrote: Some people need a good imaginary cure for their painful imaginary ailment.
DISPLAY: Some people need a good imaginary cure for their painful imaginary ailment.
DISPLAY: time: 13:08:13
DISPLAY: time: 13:08:14
DISPLAY: time: 13:08:15
DISPLAY: time: 13:08:16

撰写回答