问题
我使用带Python 3.7的eventlet 0.25.0和python-socketio 4.0.3,试图将两个Python脚本与websockets进行通信。服务器脚本运行良好:
import socketio # type: ignore
import eventlet
import json
import util as u # type: ignore
eventlet.monkey_patch()
WSGI_LOG_FORMAT = '%(client_ip)s "%(request_line)s" %(status_code)s %(body_length)s %(wall_seconds).6f'
class DatabaseServer:
""" Initializes a server using socketio and eventlet. Use start() and stop() to... start and stop it.
push() pushes new data to all clients
"""
def __init__(self):
self.server = socketio.Server(async_mode='eventlet', namespace='/socket.io')
self.server.on('connect', self.connect, namespace='/socket.io')
self.server.on('disconnect', self.disconnect, namespace='/socket.io')
self.server.on('client_response', self.client_response, namespace='/socket.io')
self.app = socketio.WSGIApp(self.server)
self.realtime_timestamp = 0
self.data_full = None
self.data_update = None
def connect(self, sid, environ):
u.server_logger.info('Client connected: %s', sid)
def client_response(self, sid, data):
u.server_logger.info('Client %s sent: %s', sid, data)
def disconnect(self, sid):
u.server_logger.info('Client disconnected: %s', sid)
def push(self):
u.server_logger.info('Pushing the realime data to web_server')
with open(u.REALTIME_PARSED_PATH + 'data_full.protobuf.bz2', 'rb') as full_infile, \
open(u.REALTIME_PARSED_PATH + 'data_update.protobuf.bz2', 'rb') as update_infile:
self.data_full = full_infile.read()
self.data_update = update_infile.read()
self.server.emit('new_data_full', self.data_full, namespace='/socket.io')
self.server.emit('new_data_update', self.data_update, namespace='/socket.io')
def server_process(self):
eventlet.wsgi.server(eventlet.listen((u.IP, u.PORT)), self.app, log=u.server_logger, log_format=WSGI_LOG_FORMAT)
def start(self):
u.server_logger.info('Starting eventlet server @ %s:%s', u.IP, u.PORT)
self.server_thread = eventlet.spawn(self.server_process)
def stop(self):
u.server_logger.info('Stopping eventlet server')
self.server_thread.kill()
而且,我可以通过浏览器轻松地与JS建立websocket连接:
var socket = io.connect('http://127.0.0.1:8000/socket.io');
socket.on('new_data_full', function(data) {
console.log('got some data_full!');
socket.emit('client_response', 'thanks!')
})
socket.on('new_data_update', function(data) {
console.log('got some data_update!');
socket.emit('client_response', 'thanks!')
})
但是!如果我尝试使用另一个Python脚本创建Websocket连接,则它仅使用轮询,而无法建立Websocket:
import socketio # type: ignore
import eventlet
import util as u # type: ignore
eventlet.monkey_patch()
DB_SERVER_URL = f'http://{u.DB_IP}:{u.DB_PORT}'
class DatabaseClient:
""" doc
"""
def __init__(self):
self.client = socketio.Client()
self.client.on('connect', self.on_connect, namespace='/socket.io')
self.client.on('disconnect', self.on_disconnect, namespace='/socket.io')
self.client.on('new_data_full', self.on_new_data_full, namespace='/socket.io')
self.client.on('new_data_update', self.on_new_data_update, namespace='/socket.io')
def start(self):
u.server_logger.info('~~~~~~~~~~~~~~~ Starting Database Client ~~~~~~~~~~~~~~~')
attempt = 0
max_attempts = 5
while True:
try:
self.client.connect(DB_SERVER_URL, namespaces=['/socket.io'])
break
except socketio.exceptions.ConnectionError as err:
if attempt < max_attempts:
attempt += 1
eventlet.sleep(1)
else:
u.server_logger.error('Unable to connect to %s, %s', DB_SERVER_URL, err)
return
eventlet.spawn(self.client.wait())
u.server_logger.info('Connected to db_server')
def stop(self):
self.client.disconnect()
def on_connect(self):
u.server_logger.info('Connected to Database Server at %s', DB_SERVER_URL)
def on_disconnect(self):
u.server_logger.info('Disconnected from Database Server at %s', DB_SERVER_URL)
# TODO: handle reconnection!
def on_new_data_full(self, data):
u.server_logger.info('Received new data_full')
self.client.emit('client_response', 'Received data_full', namespace='/socket.io')
def on_new_data_update(self, data):
u.server_logger.info('Received new data_update')
self.client.emit('client_response', 'Received data_update', namespace='/socket.io')
client = DatabaseClient()
client.start()
日志:
2019-06-13 16:33:09.935 INFO 127.0.0.1,127.0.0.1 "GET /socket.io/?transport=polling&EIO=3&t=1560457989.6019762 HTTP/1.1" 200 357 0.000298
2019-06-13 16:33:09.941 INFO Client 7dbe94bde7264ac39d03d55199184f0f sent: Thanks!
2019-06-13 16:33:09.941 INFO 127.0.0.1,127.0.0.1 "POST /socket.io/?transport=polling&EIO=3&sid=7dbe94bde7264ac39d03d55199184f0f HTTP/1.1" 200 175 0.000580
2019-06-13 16:33:09.947 INFO Client 7dbe94bde7264ac39d03d55199184f0f sent: Thanks!
2019-06-13 16:33:09.947 INFO 127.0.0.1,127.0.0.1 "POST /socket.io/?transport=polling&EIO=3&sid=7dbe94bde7264ac39d03d55199184f0f HTTP/1.1" 200 175 0.000526
答案 0 :(得分:0)
我最终意识到,不仅仅是安装:
pip install python-socketio
我应该做的:
pip install python-socketio
pip install python-socketio[client]
显然,您必须单独安装客户端模块,该客户端模块将安装名为websocket-client的软件包。现在可以使用!