Python 为什么gevent websocket是同步的?
我在玩gevent和websockets。这是一个简单的echo服务器:Python 为什么gevent websocket是同步的?,python,websocket,gevent,Python,Websocket,Gevent,我在玩gevent和websockets。这是一个简单的echo服务器: from gevent.pywsgi import WSGIServer from geventwebsocket.handler import WebSocketHandler from gevent import sleep from datetime import datetime def app(environ, start_response): ws = environ['wsgi.websocket']
from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from gevent import sleep
from datetime import datetime
def app(environ, start_response):
ws = environ['wsgi.websocket']
while True:
data = ws.receive()
print('{} got data "{}"'.format(
datetime.now().strftime('%H:%M:%S'), data))
sleep(5)
ws.send(data)
server = WSGIServer(("", 10004), app,
handler_class=WebSocketHandler)
server.serve_forever()
客户:
<html>
<body>
<button type="button" id="push_data">Push</button>
</body>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
<script>
var ws = new WebSocket("ws://localhost:10004");
ws.onmessage = function(evt) {
console.log(evt)
};
$('#push_data').click(function(){
console.log('sending data...');
ws.send('sample data');
});
</script>
</html>
为什么它会同步接收我的数据,每5秒暂停一次?如何将其转换为异步服务器?行为是同步的,因为您自己的代码是同步的。gevent只是一个使用事件循环的协同程序库。它不会神奇地将同步代码转换为异步代码 请查看以下文档: 据说服务器在每个连接(而不是每个请求)上产生一个greenlet。因此,对同一连接执行多个请求是序列化的 如果要同时处理同一连接的多个请求,则需要生成新的greenlet,或将处理委托给greenlet池 下面是一个示例(在每次请求时生成一个greenlet): 注意信号量的存在。由于处理是并发的,因此需要防止两个并发的greenlet同时在套接字上写入,从而导致消息损坏
最后一点,在这个实现中,无法保证回复将按照请求的顺序发送。实际的问题是:data=ws.receive() 这里发生的事情是,你的websocket正在等待一个连接,而整个应用程序只是挂起 您有两种解决方案,要么向ws.receive()添加超时,要么将其设置为高级应用程序:
from geventwebsocket import WebSocketServer, WebSocketApplication, Resource
class EchoApplication(WebSocketApplication):
def on_open(self):
print "Connection opened"
def on_message(self, message):
self.ws.send(message)
def on_close(self, reason):
print reason
WebSocketServer(('', 8000), Resource({'/': EchoApplication}).serve_forever()
例如:
这将使您的进程完全异步,因此发送和接收不会争夺同一资源 使用gevent进行monkey修补是否不会“神奇地将同步代码变为异步代码”?仅当您有多个Greenlet和连接时。如果代码处理的是来自单个greenlet的单个连接,那么gevent的协同路由机制将不会有帮助。换句话说,只有当你相信它,并据此构造代码时,魔法才会发生;-)
import gevent
from gevent.pywsgi import WSGIServer
from gevent.lock import Semaphore
from geventwebsocket.handler import WebSocketHandler
from datetime import datetime
def process(ws,data,sem):
print('{} got data "{}"'.format(datetime.now().strftime('%H:%M:%S'), data))
gevent.sleep(5)
with sem:
ws.send(data)
def app(environ, start_response):
ws = environ['wsgi.websocket']
sem = Semaphore()
while True:
data = ws.receive()
gevent.spawn(process,ws,data,sem)
server = WSGIServer(("", 10004), app,handler_class=WebSocketHandler)
server.serve_forever()
from geventwebsocket import WebSocketServer, WebSocketApplication, Resource
class EchoApplication(WebSocketApplication):
def on_open(self):
print "Connection opened"
def on_message(self, message):
self.ws.send(message)
def on_close(self, reason):
print reason
WebSocketServer(('', 8000), Resource({'/': EchoApplication}).serve_forever()