Socket io 未在 HTTPS 中将 nodejs 与 android(客户端)连接

时间:2021-07-29 10:15:04

标签: android node.js socket.io

使用 NodeJS 添加的自签名证书 (HTTPS) 简单地将文本形式的 NodeJS Socket io 传递给 android 客户端,我收到错误

添加:android:usesCleartextTraffic="true",互联网权限

错误:I/IO 连接错误:com.github.nkzawa.engineio.client.EngineIOException:xhr 轮询错误

我试过Android: socket.io io.socket.engineio.client.EngineIOException: XHR poll error

在那个答案中 io.set('transsports', ['websocket']);想在 nodejs 服务器中添加但是,我在我的服务器中添加了错误

Error: TypeError: Cannot read property 'transports' of undefined

帮我解决这个问题

App.js

const express = require('express')
const https = require('https')
const fs = require('fs')
const path = require('path')
const app = express()
var bodyParser = require('body-parser');
var io = require('socket.io')(https);

io.on('connection',function(socket){
    
    console.log('one user connected '+socket.id);
    socket.emit('CHAT',{"message":"hy"});
    socket.on('disconnect',function(){
        console.log('one user disconnected '+socket.id);
    });

})

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));

con.connect(function(err) {
    if (err) throw err
    console.log('You are now connected with mysql database...')
  });

app.use('/',(req,res,next) => {
    res.send('Hello from SSL server!!!')
})

const sslServer = https.createServer(
    {
        key: fs.readFileSync(path.join(__dirname,'cert','key.pem')),
        cert: fs.readFileSync(path.join(__dirname,'cert','cert.pem')),
    },
    app
)
sslServer.listen(3000, () => console.log("Secure Server on port 3000"))

MainActivity.java

public class Main2Activity extends AppCompatActivity {

    public Button button1;
    public TextView text1,text2,text3,text4;
    public EditText edit1;
    public String message;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        button1 =  findViewById(R.id.button);
        text1 =   findViewById(R.id.textview);
        edit1 =   findViewById(R.id.edit);
//        mSocket.connect();
        text1.setText("");

        final String uri = "https://192.168.43.182:3000";
        try {
            // Load CAs from an InputStream.
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            Certificate certificate = certificateFactory.generateCertificate(
                    getResources().openRawResource(R.raw.cert)); // from file server.crt
            // Create a KeyStore containing the trusted CAs.
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", certificate);
            // Create a TrustManager that trusts the CAs in KeyStore.
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);
            // Create an SSLContext that uses the TrustManager.
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            Log.i("uri", "sslContext created");

            IO.setDefaultSSLContext(sslContext);
            IO.Options options = new IO.Options();
            options.secure = true;
            options.path = "/web-live";
            options.reconnection = true;
            options.upgrade = true;
            options.sslContext = sslContext;
            URL url = new URL(uri);
            final HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
            httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
            httpsURLConnection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    Log.i("HostnameVerifier", "Approving certificate for " + hostname);
                    return true; // Do nothing.
                }
            });
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        BufferedReader in = new BufferedReader(new InputStreamReader(
                                httpsURLConnection.getInputStream()));
                        Log.i("httpsURLConnection", "url connected");
                        String line; //FIXME: readLine kicks in socket.io at least on gingerbread!?
                        while((line = in.readLine()) != null) {
                            Log.i("httpsURLConnection", line);
                        }

                        in.close();
                    } catch (IOException e) {
                    }
                }
            }).start();
            Socket socket = IO.socket(uri, options);
            socket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    for(Object o : args) {
                        Log.i("IO " + Socket.EVENT_CONNECT_ERROR, o.toString());
                    }
                }
            }).on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.i("IO", Socket.EVENT_CONNECT_TIMEOUT);
                }
            }).on(Socket.EVENT_CONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.i("IO", Socket.EVENT_CONNECT);
                }
            }).on("secure_data", new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.i("IO secure_data", args[0].toString());
                }
            });
            socket.connect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

密钥由 openssl 生成,在使用 RestApi 时它工作正常。我只有连接问题帮我解决这个问题

1 个答案:

答案 0 :(得分:0)

尝试检查以下可能在客户端和服务器之间

  • 检查您在客户端使用的 socket.io 版本是否支持在服务器(Nodejs)端使用的版本
  • 有时在成功连接或发送请求之前从客户端生成的多个请求或多个实例 待定,因此请在创建新实例之前尝试正确断开连接。
  • 尝试更新从轮询到 websocket 的传输

请检查下面的代码行可能对您有帮助

public void initSocket() {
        try {
            SSLContext mySSLContext = SSLContext.getInstance("TLS");
            mySSLContext.init(null, trustAllCerts, new SecureRandom());

            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .hostnameVerifier(myHostnameVerifier)
                    .sslSocketFactory(mySSLContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                    .build();

            IO.setDefaultOkHttpWebSocketFactory(okHttpClient);
            IO.setDefaultOkHttpCallFactory(okHttpClient);

            IO.Options opts = new IO.Options();
            opts.callFactory = okHttpClient;
            opts.webSocketFactory = okHttpClient;
            opts.timeout = 60 * 1000;
            opts.forceNew = false;
            opts.secure = true;
            opts.reconnection = true;

            mSocket = IO.socket(socketUrl, opts);
            mSocket.connect();

            mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG,"socket connected");
                }
            }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG,"socket disconnected");
                }
            }).on(Socket.EVENT_ERROR, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG,"socket error");
                }

            }).on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
                @Override
                public void call(Object... args) {
                    Log.e(TAG,"socket connection timeout");
                }
            });

        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


   TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[]{};
        }

        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
    }};

    HostnameVerifier myHostnameVerifier = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };
相关问题