简体   繁体   中英

SocketIo integration with Django

I have been trying to integrate socketio with Django, And I am getting the following error.

[31/Mar/2020 14:50:27] "GET /socket.io/?EIO=3&transport=polling&t=N4n4ds4&b64=1 HTTP/1.1" 200 117
[31/Mar/2020 14:50:27] "POST /socket.io/?EIO=3&transport=polling&t=N4n4dsj&b64=1&sid=9053be92266c46148304c09833b2ebe8 HTTP/1.1" 200 2
Traceback (most recent call last):
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/wsgiref/handlers.py", line 137, in run
    self.result = application(self.environ, self.start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/django/contrib/staticfiles/handlers.py", line 68, in __call__
    return self.application(environ, start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/engineio/middleware.py", line 60, in __call__
    return self.engineio_app.handle_request(environ, start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/socketio/server.py", line 558, in handle_request
    return self.eio.handle_request(environ, start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/engineio/server.py", line 377, in handle_request
    environ, start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/engineio/socket.py", line 108, in handle_get_request
    start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/engineio/socket.py", line 152, in _upgrade_websocket
    return ws(environ, start_response)
  File "/Users/murali/yourenv/lib/python3.7/site-packages/engineio/async_drivers/eventlet.py", line 16, in __call__
    raise RuntimeError('You need to use the eventlet server. '
RuntimeError: You need to use the eventlet server. See the Deployment section of the documentation for more information.
[31/Mar/2020 14:50:27] "GET /socket.io/?EIO=3&transport=websocket&sid=9053be92266c46148304c09833b2ebe8 HTTP/1.1" 500 59
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 52220)
Traceback (most recent call last):
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socketserver.py", line 720, in __init__
    self.handle()
  File "/Users/murali/yourenv/lib/python3.7/site-packages/django/core/servers/basehttp.py", line 174, in handle
    self.handle_one_request()
  File "/Users/murali/yourenv/lib/python3.7/site-packages/django/core/servers/basehttp.py", line 182, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 589, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [Errno 54] Connection reset by peer
----------------------------------------

The link I was referring https://www.botreetechnologies.com/blog/django-websocket-with-socketio

Below is my code:

requirements.txt:

enum-compat==0.0.2
eventlet==0.25.1
python-engineio
python-socketio
pytz==2018.7
six==1.10.0

settings.py: added socketio in INSTALLED_APPS:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'socketio'
]

wsgi.py:

import os
import eventlet
import socketio
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'integrate_socketio.settings')

application = get_wsgi_application()
sio = socketio.Server()
application = socketio.WSGIApp(sio, application)

urls.py

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    #path('admin/', admin.site.urls),
    path('', views.hello, name='hello')
]

view.py

import eventlet
async_mode = eventlet
import os
from django.http import HttpResponse
import socketio

basedir = os.path.dirname(os.path.realpath(__file__))
sio = socketio.Server(async_mode='eventlet')\

@sio.on('connection-bind')
def connection_bind(sid, data):
    print("sid:",sid,"data",data)

@sio.on('message')
def message(data):
    print(data)
    sio.emit('test',data)
@sio.on('disconnect')
def test_disconnect(sid):
    print("Disconnected")
def hello(data):
    return HttpResponse("Hello")

Below is the code for client written in nodejs,

var io = require('socket.io-client');
var socket = io.connect('http://localhost:8000', {reconnect: false});

socket.on('connect', function (socket) {
    console.log('Connected!');
});
socket.emit('message', 'messgae', 'test msg');
socket.on('test', function (data) {
    console.log(data);
})

To run:

python manage.py runserver

I get response when I open http://localhost:8000/ in the browser, but above error comes when I run nodejs client.

Any help would be appreciated :)

Thanks in advance...!

Problem

The problem is the async_mode parameter for the socketio.Server instance (the sio ). The parameter basically chooses what model to use when running. Each model type needs to be run in a certain way. The default for async_mode is 'eventlet' , which means that the SocketIO server needs to be run with eventlet. In your case, it seems that it has defaulted to 'eventlet' , but you aren't running your django server with eventlet, which is raising an error. To fix this, you can either change the sio parameters to be compatible with your way of (solution 1) or you can configure your wsgi.py to run the server with eventlet (solution 2).


Solution 1

You can change the sio parameters on initialization as follows:

sio = socketio.Server(async_mode='mode') # Change 'mode' to your mode

You can change 'mode' based on how you are running your server. The options are 'gevent_uwsgi' , 'gevent' , or 'threading' (or 'eventlet' , None , but neither would solve your problem).

By the looks of your run statement, you aren't using gunicorn or uwsgi, so in your case, it would be best if you used threading or gevent . (The instructions for using gunicorn or uwsgi with 'gevent' or 'gevent_uwsgi' respectively are in the official docs cited at the bottom)

If you are using 'threading' , you don't need to install anything or change anything in your wsgi.py (other than the mode), but it is comparatively slower in terms of performance.

If you are using 'gevent' , you would need to install gevent as follows:

$ pip install gevent

Then, you would need to change some settings in wsgi.py. If you have the gevent websocket transport installed then add the following to the bottom of your wsgi.py:

from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
pywsgi.WSGIServer(('', 8000), app, 
    handler_class=WebSocketHandler).serve_forever()

If not, then add the following instead:

from gevent import pywsgi
pywsgi.WSGIServer(('', 8000), app).serve_forever()

Solution 2

If you decide to configure your wsgi.py to run with eventlet, you first install eventlet...

$ pip install eventlet

...and add the following to the bottom of your wsgi.py:

import eventlet
import eventlet.wsgi
eventlet.wsgi.server(eventlet.listen(('', 8000)), application)

Citation

I got all the info from this website and the official socket.io documentation . The official documentation also has instructions for using the other modes from "solution 1"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM