简体   繁体   English

如何将Android应用程序连接到python-socketio后端?

[英]How to connect Android app to python-socketio backend?

I am currently running a Python SocketIO server that connects perfectly to my JavaScript Client. 我目前正在运行可完美连接到我的JavaScript客户端的Python SocketIO服务器。 I am using the socketio android example chat app to write the Android code, it worked perfectly with a NodeJS server but when I change over to using the Python server it won't connect. 我正在使用socketio android示例聊天应用程序编写Android代码,它与NodeJS服务器完美配合,但是当我改用Python服务器时,它将无法连接。

How can I connect to the Ptyhon-SocketIO server from Android? 如何从Android连接到Ptyhon-SocketIO服务器?

Android code: Android代码:

public class HomeActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {

private final String TAG = "MainActivity";

Button btnCore0, btnCore1, btnCPUUsage;
private ProgressBar progressBar;

private Socket mSocket;

{
    try {
        mSocket = IO.socket(Constants.SERVER_URL);
    } catch (URISyntaxException e) {
        Log.e(TAG, e.getMessage());
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    btnCore0 = (Button) findViewById(R.id.btnCore0);
    btnCore1 = (Button) findViewById(R.id.btnCore1);
    btnCPUUsage = (Button) findViewById(R.id.btnCPUUsage);
    progressBar = (ProgressBar) findViewById(R.id.progressBar);

    // Make buttons invisible
    btnCore0.setVisibility(View.INVISIBLE);
    btnCore1.setVisibility(View.INVISIBLE);
    btnCPUUsage.setVisibility(View.INVISIBLE);
    // Make progress bar visible
    progressBar.setVisibility(View.VISIBLE);

    mSocket.on("status-update", onNewMessage);
    mSocket.on(Socket.EVENT_DISCONNECT, onSocketDisconnected);
    mSocket.connect();
}

private Emitter.Listener onNewMessage = new Emitter.Listener() {
    @Override
    public void call(final Object... args) {
        HomeActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "New message 090909***");
                JSONObject data = (JSONObject) args[0];
                int core0 = 0;
                int core1 = 0;
                int cpu_usage_in = 0;
                try {
                    core0 = data.getInt("core0_in");
                    core1 = data.getInt("core1_in");
                    cpu_usage_in = data.getInt("cpu_usage_in");
                } catch (JSONException e) {
                    Log.e(TAG, e.getMessage());
                }

                btnCore0.setText(getResources().getString(R.string.core0, String.valueOf(core0)));
                btnCore1.setText(getResources().getString(R.string.core1, String.valueOf(core1)));
                btnCPUUsage.setText(getResources().getString(R.string.cpu_usge, String.valueOf(cpu_usage_in)));

                updateButtonBackgroundColor(btnCore0, core0);
                updateButtonBackgroundColor(btnCore1, core1);
                updateButtonBackgroundColor(btnCPUUsage, cpu_usage_in);

                onServerDataReceived();
            }
        });
    }
};

Next is the Pyhton server that emits every second. 接下来是每秒发出一次的Pyhton服务器。 This, I know works fine as I can connect to it from a JavaScript app. 我知道这很好用,因为我可以从JavaScript应用程序连接到它。 Python code: Python代码:

from flask import Flask, render_template
from flask_socketio import SocketIO
from gcm import GCM

eventlet.monkey_patch()
app = Flask(__name__)
socket = SocketIO(app, logger=True, engineio_logger=True)

class Server(threading.Thread):
def __init__(self, thread_id):
    threading.Thread.__init__(self)
    self.threadID = thread_id

def run(self):
    print("Starting " + self.name)
    serve()
    print("Exiting " + self.name)


def serve():
if __name__ == '__main__':
    eventlet.wsgi.server(eventlet.wrap_ssl(eventlet.listen(('', 8000)), certfile='/home/garthtee/cert.pem', keyfile='/home/garthtee/privkey.pem'), app)

server_thread = Server("Server-thread")
server_thread.start()
threads.append(server_thread)
print("Started @ " + str(get_time()))
while True:
sensors.init()
try:
    for chip in sensors.iter_detected_chips():
        # print('%s at %s' % (chip, chip.adapter_name))
        for feature in chip:
            if feature.label == 'Core 0':
                core0 = feature.get_value()
            elif feature.label == 'Core 1':
                core1 = feature.get_value()
    for x in range(1):
        cpu_usage = str(psutil.cpu_percent(interval=1))
finally:
    socket.emit('status-update', {'core0_in': core0, 'core1_in': core1, 'cpu_usage_in': cpu_usage, 'users': users})

    alert_checker(avg_temp, users)
    sensors.cleanup()
    time.sleep(1)

The following error shows up: 出现以下错误:

SSLError: [SSL: SSL_HANDSHAKE_FAILURE] ssl handshake failure (_ssl.c:1754) SSLError:[SSL:SSL_HANDSHAKE_FAILURE] SSL握手失败(_ssl.c:1754)

I downloaded the SocketIO python library from Github 我从Github下载SocketIO python库

I modified the example code like this: 我修改了示例代码,如下所示:

import socketio
import eventlet
import eventlet.wsgi
from flask import Flask, render_template

sio = socketio.Server()
app = Flask(__name__)

@app.route('/')
def index():
    """Serve the client-side application."""
    return render_template('index.html')

@sio.on('connect', namespace='/')
def connect(sid, environ):
    print("connect ", sid)

@sio.on('add user', namespace='/')
def login(sid, environ):
    print("login ", sid)
    sio.emit('login', room=sid)

@sio.on('new message', namespace='/')
def message(sid, data):
    print("message ", data)
    sio.emit('reply', room=sid)

@sio.on('disconnect', namespace='/')
def disconnect(sid):
    print('disconnect ', sid)

if __name__ == '__main__':
    # wrap Flask application with engineio's middleware
    app = socketio.Middleware(sio, app)

    # deploy as an eventlet WSGI server
    eventlet.wsgi.server(eventlet.listen(('', 8000)), app)

Then I cloned the Android example chat project, and the only thing what I changed in the Constants.java: 然后,我克隆了Android示例聊天项目,这是我在Constants.java中所做的唯一更改:

public static final String CHAT_SERVER_URL = "http://MY_LOCAL_IP:8000";

And the Android app can connect. 并且Android应用程序可以连接。 I see it in the app, and also in the python console. 我在应用程序和python控制台中都看到了它。 If you remove some unnecessary parsing part (the app is crashing, because the response is different), you can also see your messages in python. 如果您删除了一些不必要的解析部分(由于响应不同,则应用程序崩溃了),您还可以在python中查看消息。

Have you tried to run your server app without SSL first? 您是否尝试过先运行没有SSL的服务器应用程序?

Maybe that is the problem. 也许这就是问题所在。 On Android you can use IO.setDefaultSSLContext(SSLContext sslContext) to setup SSL. 在Android上,您可以使用IO.setDefaultSSLContext(SSLContext sslContext)来设置SSL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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