创建一个Simpe Python Web套接字服务器

时间:2017-08-07 02:15:33

标签: python websocket

我正在尝试使用this module在Python中实现一个简单的Web套接字服务器。出于学习目的,服务器应回复其收到的反向版本。例如,如果客户端发送“Hello Server”,则服务器应以“revreS olleH”响应。我的代码基于文档here

由于文档中未提供consumer()producer()函数/协同程序的示例,因此我尝试创建它们,但认为我误解了对我来说不明显的事情。代码当前返回字符串'nothing',而不是客户端发送的反转版本。

仅供参考,因为我使用的机器有Python 3.4.3,所以必须调整代码以适应该版本。这就是为什么你现在会看到更新的代码被注释掉的原因。当我学习这些东西时,也包含了大量的文档。

现在,代码...

index.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-



#########################
# Dependencies
#########################
# asyncio
# websockets



#########################
# Modules
#########################

import asyncio
import websockets



#########################
# Functions
#########################

# async indicates an asynchronous function.
# Calling them doesn't actually run them,
# but instead a coroutine object is returned,
# which can then be passed to the event loop to be executed later on.

# Python ≥ 3.5: async def producer(reply):
@asyncio.coroutine
def producer(reply=None):
    """Sends the reply to producer_handler."""

    if reply is None:
        return 'nothing'
    else:
        return reply

# Python ≥ 3.5: async def consumer(message):
@asyncio.coroutine
def consumer(message):
    """Reverses message then sends it to the producer."""

    reply = message[::-1]
    #await producer(reply)
    yield from producer(reply)

# async def consumer_handler(websocket):
@asyncio.coroutine
def consumer_handler(websocket):
    """Handles incoming websocket messages."""

    while True:
        # await calls an asynchronous function.
        #message = await websocket.recv()
        message = yield from websocket.recv()
        # Python ≥ 3.5: await consumer(message)
        yield from consumer(message)

#async def producer_handler(websocket):
@asyncio.coroutine
def producer_handler(websocket):
    """Handles outgoing websocket messages."""

    while True:
        #message = await producer()
        message = yield from producer()
        #await websocket.send(message)
        yield from websocket.send(message)

#async def handler(websocket, path):
@asyncio.coroutine
def handler(websocket, path):
    """Enables reading and writing messages on the same websocket connection."""

    # A Future is an object that is supposed to have a result in the future.

    # ensure_future:
    # schedules the execution of a coroutine object,
    # wraps it in a future, then returns a Task object.
    # If the argument is a Future, it is returned directly.

    # Python ≥ 3.5
    #consumer_task = asyncio.ensure_future(consumer_handler(websocket))
    #producer_task = asyncio.ensure_future(producer_handler(websocket))

    consumer_task = asyncio.async(consumer_handler(websocket))
    producer_task = asyncio.async(producer_handler(websocket))

    # .wait:
    # wait for the Futures and coroutine objects given
    # by the sequence futures to complete. Coroutines will be
    # wrapped in Tasks. Returns two sets of Future: (done, pending).

    #done, pending = await asyncio.wait(
    done, pending = yield from asyncio.wait(
        # The futures.
        [consumer_task, producer_task],
        # FIRST_COMPLETED: the function will return when
        # any future finishes or is cancelled.
        return_when=asyncio.FIRST_COMPLETED,
    )
    for task in pending:
        task.cancel()



#########################
# Start script
#########################

def main():

    # Creates a WebSocket server.
    start_server = websockets.serve(handler, '127.0.0.1', 8000)

    # Get the event loop for the current context.
    # Run until the Future is done.
    asyncio.get_event_loop().run_until_complete(start_server)

    # Run until stop() is called.
    asyncio.get_event_loop().run_forever()



#########################
# Script entry point.
#########################

if __name__ == '__main__':
    main()

的index.html

<!DOCTYPE html>
<html>
    <head>
        <title>WebSocket demo</title>
    </head>
    <body>
        <script>
            // Create the websocket.
            var ws = new WebSocket("ws://127.0.0.1:8000/"),
                messages = document.createElement('ul');

            // Called when the websocket is opened.
            ws.onopen = function(event) {
                ws.send('Hello Server!');
            };

            // Called when a message is received from server.
            ws.onmessage = function(event) {
                var messages = document.getElementsByTagName('ul')[0],
                    message = document.createElement('li'),
                    content = document.createTextNode(event.data);
                message.appendChild(content);
                messages.appendChild(message);
            };
            document.body.appendChild(messages);
        </script>
    </body>
</html>

1 个答案:

答案 0 :(得分:1)

对此并不完全确定,但我认为你误解了文档。消费者不应该打电话给制作人。

&#34; Hello Server!&#34; HTML文件发送通过consumer_handlerconsumerproducer,但yield from语句表示反向字符串最终返回consumer_handler,如yield from consumer(message)的结果。

另一方面,producer_handler多次调用producer而没有参数(来自message = yield from producer()),这就是创建发送到HTML文件的nothing的内容。它没有收到consumer的字符串。

相反,应该有一个队列或消费者推送的东西,生产者从like in this example获取。

感谢。