简体   繁体   中英

flask-socketio doesn't allow connection from android device

Ok so I am following these tutorials to build a socketIO server using flask-socketIO and a client app for android devices . My python setup is pretty simple:

Python server:

init.py:

from flask import Flask, render_template
from flask.ext.socketio import SocketIO, emit
import logging
from os import getcwd
from datetime import datetime 

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

def openDir(folder):
    import os, errno

    try:
        os.makedirs(folder)
    except OSError, e:
        if e.errno != errno.EEXIST:
            raise

openDir('logs')

def fileAndChannelLogger(file_location,name):
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler("".join([getcwd(),'/',file_location,'/',datetime.today().strftime("%Y%m%d_%H_%M"),"_",name,".log"]))
    fh.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(levelname)s | %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)

    logger.addHandler(fh)
    logger.addHandler(ch)

    return logger

logger = fileAndChannelLogger('logs', 'test')

@app.route('/')
def index():
    logger.debug("Someone accessed the root page")
    return render_template('index.html')

@socketio.on('connect', namespace='/test')
def test_connect():
    logger.debug('Client connected')

@socketio.on('new message', namespace='/test')
def new_message(message):
    logger.debug(message)

@socketio.on('disconnect', namespace='/test')
def test_disconnect():
    logger.debug('Client disconnected')

run.py

from app import app, socketio
if __name__ == '__main__':
    socketio.run(app,host='My_cool_host_name')

Android client:

MainActivity.java

import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.net.URISyntaxException;
import java.util.Objects;

import com.github.nkzawa.emitter.Emitter;
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;

import org.json.JSONException;
import org.json.JSONObject;

import static android.app.PendingIntent.getActivity;

public class MainActivity extends Activity implements View.OnClickListener {
    EditText userID;
    EditText statement;

    private Socket mSocket;
    {
        try {
            mSocket = IO.socket("http://My_cool_host_name:5000/test");
        } catch (URISyntaxException e) {}
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSocket.connect();
        Button send = (Button) findViewById(R.id.sendBtn);
        send.setOnClickListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View v) {
        String ID_data = userID.getText().toString();
        String statement_data = statement.getText().toString();
        if (TextUtils.isEmpty(ID_data)) {
            return;
        }
        if (TextUtils.isEmpty(statement_data)) {
            return;
        }

        statement.setText("");
        JSONObject json = new JSONObject();
        try {
            json.put("user",ID_data);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        try {
            json.put("statement",statement_data);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        mSocket.emit("new message",json);
    }
}

Basically it takes in two edit boxes and then passes the info off to the server, nothing super fancy, just enough to get the basic groundwork of how this all works. I start the server, I can see the index.html from my browser when I go to the address with the specified port, when I run the client app in my an emulated device I get this error in the console:

 * Running on http://My_cool_host_name:5000/
2015-08-05 22:37:31,311 - DEBUG | Someone accessed the root page
192.168.1.163 - - [2015-08-05 22:37:31] "GET / HTTP/1.1" 200 210 0.022884
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/gevent/pywsgi.py", line 508, in handle_                                                                                                                                                             one_response
    self.run_application()
  File "/usr/lib/python2.7/site-packages/gevent/pywsgi.py", line 494, in run_app                                                                                                                                                             lication
    self.result = self.application(self.environ, self.start_response)
  File "/usr/lib/python2.7/site-packages/flask_socketio/__init__.py", line 27, i                                                                                                                                                             n __call__
    raise RuntimeError('You need to use a gevent-socketio server.')
RuntimeError: You need to use a gevent-socketio server.
{'GATEWAY_INTERFACE': 'CGI/1.1',
 'HTTP_ACCEPT_ENCODING': 'gzip',
 'HTTP_CONNECTION': 'Keep-Alive',
 'HTTP_HOST': 'My_cool_host_name:5000',
 'HTTP_USER_AGENT': 'Dalvik/2.1.0 (Linux; U; Android 5.1; Android SDK built for                                                                                                                                                              x86 Build/LKY45)',
 'PATH_INFO': '/socket.io/',
 'QUERY_STRING': 'EIO=3&transport=polling',
 'REMOTE_ADDR': '192.168.1.163',
 'REMOTE_PORT': '57754',
 'REQUEST_METHOD': 'GET',
 'SCRIPT_NAME': '',
 'SERVER_NAME': 'server_name',
 'SERVER_PORT': '5000',
 'SERVER_PROTOCOL': 'HTTP/1.1',
 'SERVER_SOFTWARE': 'gevent/1.0 Python/2.7',
 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x7f344d15b1e0>,
 'wsgi.input': <gevent.pywsgi.Input object at 0x7f34461ddd10>,
 'wsgi.multiprocess': False,
 'wsgi.multithread': False,
 'wsgi.run_once': False,
 'wsgi.url_scheme': 'http',
 'wsgi.version': (1, 0)} failed with RuntimeError

192.168.1.163 - - [2015-08-05 22:39:08] "GET /socket.io/?EIO=3&transport=polling HTTP/1.1" 500 161 0.010306

As you can see it says something about

You need to use a gevent-socketio server.

But I thought I could just run it like this, do I need to turn around and shuffle this behind a gevent-socketio server just for this simple test? If so can someone recommend a direction? These are my installed python libraries:

alembic==0.6.2
Babel==1.3
Beaker==1.7.0.dev0
BeautifulSoup==3.2.1
blinker==1.3
decorator==3.4.0
Flask==0.10.1
Flask-Babel==0.9
Flask-Bootstrap==3.0.3.1
Flask-Login==0.2.9
Flask-Mail==0.9.0
Flask-Migrate==1.1.0
Flask-Mobility==0.1.1
Flask-Passlib==0.1
Flask-Script==0.6.6
Flask-Scrypt==0.1.3.1
Flask-SocketIO==0.6.0
Flask-SQLAlchemy==1.0
Flask-WhooshAlchemy==0.55a0
Flask-WTF==0.9.4
flup==1.0.2
gevent==1.0
gevent-socketio==0.3.6
gevent-websocket==0.9.2
greenlet==0.4.2
itsdangerous==0.24
Jinja2==2.8
lxml==3.4.4
Mako==0.9.1
MarkupSafe==0.23
MySQL-python==1.2.5
netsnmp-python==1.0a1
numpy==1.9.2
parse==1.6.3
passlib==1.6.2
pycrypto==2.6.1
python-dateutil==2.4.2
pytz==2013.9
PyYAML==3.11
scipy==0.15.1
scrypt==0.6.1
selenium==2.45.0
six==1.9.0
speaklater==1.3
SQLAlchemy==0.7.10
sqlalchemy-migrate==0.7.2
team==1.0
Tempita==0.5.1
Twisted==15.2.1
ujson==1.33
uWSGI==2.0.10
Werkzeug==0.10.4
Whoosh==2.5.6
WTForms==1.0.5
XlsxWriter==0.7.3
yamlog==0.9
zope.interface==4.1.2

Any help would be greatly appreciated, thanks.

Sadly,I also meet the same problems and doesn't know how to solve it. While waiting for some's answer here, I try another library https://github.com/koush/AndroidAsync , and luckily it works. Maybe you can have a try.

I had a similar issue, and it wound up being about the encoding that flask-socketio uses when communicating with Android. Try:

 mSocket = IO.socket("http://My_cool_host_name:5000/test?b64=1");

See this thread for more details:

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