0

这是我想要达到的 Szenario:

我想使用 vuzix m100(Android API 15)和 Google Chrome 浏览器/或者 Firefox 开发 2 路远程视频会议。为了达到这个连接,我使用 WebRTC 和一个带有 Websockets 的 Node.JS 服务器来启用两个客户端的查找。

我目前面临的问题是,如果我将 2 个 Chrome 浏览器客户端详细连接到一个 Android 设备(Sony Xperia z 3 compact)和一个桌面电脑,那么一切都可以完美运行。如果我尝试通过浏览器连接我的 Vuzix,则会收到没有主机路由的错误消息。

node.js 服务器:

  var fs = require('fs');
var https = require('https');
var privateKey  = fs.readFileSync('server.key', 'utf8');
var certificate = fs.readFileSync('server.crt', 'utf8');

var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();

//require our websocket library 
var WebSocketServer = require('ws').Server; 

var httpsServer = https.createServer(credentials, app);
httpsServer.listen(9090);

//creating a websocket server at port 9090 
// var wss = new WebSocketServer({port: 9090}, {}); 

var wss = new WebSocketServer({
  server : httpsServer
})


//all connected to the server users 
var users = {};

//when a user connects to our sever 
wss.on('connection', function(connection) {

   console.log("User connected");

   //when server gets a message from a connected user 
   connection.on('message', function(message) { 

      var data; 

      //accepting only JSON messages 
      try { 
         data = JSON.parse(message); 
      } catch (e) { 
         console.log("Invalid JSON"); 
         data = {}; 
      }

      //switching type of the user message 
      switch (data.type) { 
         //when a user tries to login
         case "login": 
            console.log("User logged", data.name); 

            //if anyone is logged in with this username then refuse 
            if(users[data.name]) { 
               sendTo(connection, { 
                  type: "login", 
                  success: false 
               }); 
            } else { 
               //save user connection on the server 
               users[data.name] = connection; 
               connection.name = data.name; 

               sendTo(connection, { 
                  type: "login", 
                  success: true 
               }); 
            } 

            break;

         case "offer": 
            //for ex. UserA wants to call UserB 
            console.log("Sending offer to: ", data.name);

            //if UserB exists then send him offer details 
            var conn = users[data.name]; 

            if(conn != null) { 
               //setting that UserA connected with UserB 
               connection.otherName = data.name; 

               sendTo(conn, { 
                  type: "offer", 
                  offer: data.offer, 
                  name: connection.name 
               }); 
            }

            break;

         case "answer": 
            console.log("Sending answer to: ", data.name); 
            //for ex. UserB answers UserA 
            var conn = users[data.name]; 

            if(conn != null) { 
               connection.otherName = data.name; 
               sendTo(conn, { 
                  type: "answer", 
                  answer: data.answer 
               }); 
            } 

            break; 

         case "candidate": 
            console.log("Sending candidate to:",data.name); 
            var conn = users[data.name];

            if(conn != null) { 
               sendTo(conn, { 
                  type: "candidate", 
                  candidate: data.candidate 
               }); 
            } 

            break;

         case "leave": 
            console.log("Disconnecting from", data.name); 
            var conn = users[data.name]; 
            conn.otherName = null; 

            //notify the other user so he can disconnect his peer connection 
            if(conn != null) {
               sendTo(conn, { 
                  type: "leave" 
              }); 
            }

            break;

         default: 
            sendTo(connection, { 
               type: "error", 
               message: "Command not found: " + data.type 
            }); 

            break; 
      }

   }); 

   //when user exits, for example closes a browser window 
   //this may help if we are still in "offer","answer" or "candidate" state 
   connection.on("close", function() { 

      if(connection.name) { 
         delete users[connection.name]; 

         if(connection.otherName) { 
            console.log("Disconnecting from ", connection.otherName); 
            var conn = users[connection.otherName]; 
            conn.otherName = null;

            if(conn != null) { 
               sendTo(conn, { 
                  type: "leave" 
               }); 
            }
         } 
      }

   });  

   connection.send("Hello world");  
});

function sendTo(connection, message) { 
   connection.send(JSON.stringify(message)); 
}

安卓应用:

public class ServerConnection {
    private WebSocketFactory webSocketfactory;
    private WebSocket ws;
    private MediaStream mS;
    private PeerConnectionFactory peerFactory;
    private PeerConnection yourConn;
    private MediaConstraints sdpConstraints;
    private SessionObserver sessionObserver = new SessionObserver();
    private PeerObserver peerObserver = new PeerObserver();
    private String connectedUser;

    public ServerConnection(MediaStream mS, PeerConnectionFactory peerFactory) {
        this.webSocketfactory = new WebSocketFactory();
        this.mS = mS;
        this.peerFactory = peerFactory;
        // Create a custom SSL context.
        SSLContext context = null;
        try {
            context = NaiveSSLContext.getInstance("TLS");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        // Set the custom SSL context.
        webSocketfactory.setSSLContext(context);
        initWebsockets();

    }

    public void sendMessage(String message) {
        if (connectedUser != null) {
            try {
                JSONObject json = new JSONObject(message);
                json.put("name", connectedUser);
                ws.sendText(json.toString());
            } catch (JSONException e) {
                e.printStackTrace();
            }

        } else {
            Log.e("String s", message);
            ws.sendText(message);

        }
    }

    private void initWebsockets() {
        try {
            ws = webSocketfactory.createSocket("wss://192.168.179.36:9090");
            ws.addListener(new SocketListener());
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        ws.connect();
                    } catch (WebSocketException e) {
                        e.printStackTrace();
                        initWebsockets();
                    }
                }
            });
            t.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class SocketListener extends WebSocketAdapter {
        @Override
        public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
            Log.e("connected", "connected");
            JSONObject json = new JSONObject();
            try {
                // Für den Anfang statisch
                json.put("type", "login");
                json.put("name", "John");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            sendMessage(json.toString());
        }


        @Override
        public void onConnectError(WebSocket websocket, WebSocketException exception) throws Exception {
            Log.e("onError", exception.getMessage());
        }


        @Override
        public void onDisconnected(WebSocket websocket,
                                   WebSocketFrame serverCloseFrame, WebSocketFrame clientCloseFrame,
                                   boolean closedByServer) throws Exception {
        }

        @Override
        public void onTextMessage(WebSocket websocket, String text) throws Exception {
            Log.e("Got Message", text);
            JSONObject json = new JSONObject(text);
            if (json != null) {
                switch (json.getString("type")) {
                    case "login":
                        Log.e("Condition", json.getString("success"));
                        handleLogin(json.getBoolean("success"));
                        break;
                    case "offer":
                        handleOffer(json.getString("offer"), json.getString("name"));
                        break;
                    case "answer":
                        handleAnswer(json.getString("answer"));
                        break;
                    case "candidate":
                        String candidate = json.getString("candidate");
                        handleCandidate(candidate);
                        break;
                    case "leave":
                        break;
                    default:
                        break;
                }
            }
        }


        @Override
        public void onFrameSent(WebSocket websocket, WebSocketFrame frame) throws Exception {
            Log.e("sent", frame.getPayloadText());
        }
    }


    private void handleLogin(boolean success) {
        if (!success) {
            Log.e("handleLogin", "Try a different Username");
        } else {
            List<PeerConnection.IceServer> server = new ArrayList<>();
            server.add(new PeerConnection.IceServer("stun:stun2.1.google.com:19302"));
            server.add(new PeerConnection.IceServer("turn:192.158.29.39:3478?transport=udp", "28224511:1379330808", "JZEOEt2V3Qb0y27GRntt2u2PAYA="));
            sdpConstraints = new MediaConstraints();
            sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
            sdpConstraints.optional.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));

            yourConn = peerFactory.createPeerConnection(server, sdpConstraints, peerObserver);
            Log.e("Media Stream:", mS.toString());
            yourConn.addStream(mS);

            // wird später implementiert um anrufe zu starten
            // yourConn.createOffer(new SessionObserver(), sdpConstraints);
        }
    }


    private void handleOffer(String offer, String name) {
        try {
            JSONObject sdp = new JSONObject(offer);

            connectedUser = name;
            SessionDescription sessionDescription = new SessionDescription(SessionDescription.Type.OFFER, sdp.getString("sdp"));
            yourConn.setRemoteDescription(sessionObserver, sessionDescription);

            yourConn.createAnswer(sessionObserver, sdpConstraints);
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }


    private void handleAnswer(String answer) {
        try {
            Log.e("answer", answer);
            JSONObject sdp = new JSONObject(answer);
            SessionDescription sessionDescription = new SessionDescription(SessionDescription.Type.ANSWER, sdp.getString("sdp"));
            yourConn.setRemoteDescription(sessionObserver, sessionDescription);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    private void handleLeave() {
    }

    private void handleCandidate(String candidate) {
        Log.e("handleCandidate", candidate);

        //yourConn.addIceCandidate(new IceCandidate())
//        try {
//            JSONObject candidateJson = new JSONObject();
//            candidateJson.put("type", "candidate");
//            JSONObject candidateInfosJSON = new JSONObject(candidate);
//            candidateJson.put("candidate", candidateInfosJSON);
//
//            sendMessage(candidateJson.toString());
//        } catch (JSONException e) {
//            e.printStackTrace();
//        }
    }


    class PeerObserver implements PeerConnection.Observer {
        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {
            Log.e("onSignalingChange", "");
        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
            Log.e("onIceConnectionChange", "");

        }

        @Override
        public void onIceConnectionReceivingChange(boolean b) {
            Log.e("onIceConnectionChange", "");
        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
            Log.e("onIceGatheringChange", "");
        }

        @Override
        public void onIceCandidate(IceCandidate iceCandidate) {
//            Log.e("onIceCandidate", iceCandidate.toString());
//            JSONObject candidate = new JSONObject();
//            try {
//
//                candidate.put("type", "candidate");
//                candidate.put("label", iceCandidate.sdpMLineIndex);
//                candidate.put("id", iceCandidate.sdpMid);
//                candidate.put("candidate", iceCandidate);
            Log.e("OnIceCandidate", "here");


//            } catch (JSONException e) {
//                e.printStackTrace();
//            }

        }

        @Override
        public void onAddStream(MediaStream mediaStream) {
            Log.e("onAddStream", "Stream added: " + mediaStream);

        }

        @Override
        public void onRemoveStream(MediaStream mediaStream) {
            Log.e("onRemoveStream", "Removed mediaStream: " + mediaStream);
        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {
            Log.e("onDataChannel", "");
        }

        @Override
        public void onRenegotiationNeeded() {
            Log.e("onRenegotiationNeeded", "");
        }

    }


    class SessionObserver implements SdpObserver {

        @Override
        public void onCreateSuccess(SessionDescription sessionDescription) {
            Log.e("Session", "sending");
            JSONObject session = new JSONObject();
            JSONObject answer = new JSONObject();
            try {
                String answerORoffer = sessionDescription.type.toString().toLowerCase();
                session.put("type", answerORoffer);
                answer.put("type", answerORoffer);
                answer.put("sdp", sessionDescription.description);
                session.put(answerORoffer, answer);
                Log.e("SESSION", session.toString());
                //session.put(answerORoffer, sessionDescription.description);

                sendMessage(session.toString());
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onSetSuccess() {
            Log.e("do call success", ".....");
        }

        @Override
        public void onCreateFailure(String s) {
            Log.e("do call failure", s);

        }

        @Override
        public void onSetFailure(String s) {
            Log.e("onSetFailure", s);

        }
    }

}

需要提到的重要一点是错误出现在 initWebSockets 函数中

我得到的错误:

    09-22 15:41:47.056 7682-7779/com.mobile_function.webrtc_android W/System.err: com.neovisionaries.ws.client.WebSocketException: Failed to connect to '192.168.179.36:9090': failed to connect to /192.168.179.36 (port 9090): connect failed: EHOSTUNREACH (No route to host)
09-22 15:41:47.056 7682-7779/com.mobile_function.webrtc_android W/System.err:     at com.neovisionaries.ws.client.SocketConnector.doConnect(SocketConnector.java:119)
09-22 15:41:47.056 7682-7779/com.mobile_function.webrtc_android W/System.err:     at com.neovisionaries.ws.client.SocketConnector.connect(SocketConnector.java:81)
09-22 15:41:47.064 7682-7779/com.mobile_function.webrtc_android W/System.err:     at com.neovisionaries.ws.client.WebSocket.connect(WebSocket.java:2022)
09-22 15:41:47.064 7682-7779/com.mobile_function.webrtc_android W/System.err:     at com.mobile_function.webrtc_android.ServerConnection$1.run(ServerConnection.java:84)
09-22 15:41:47.064 7682-7779/com.mobile_function.webrtc_android W/System.err:     at java.lang.Thread.run(Thread.java:856)
09-22 15:41:47.064 7682-7779/com.mobile_function.webrtc_android W/System.err: Caused by: java.net.ConnectException: failed to connect to /192.168.179.36 (port 9090): connect failed: EHOSTUNREACH (No route to host)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:114)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:     at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:     at java.net.Socket.connect(Socket.java:842)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:     at com.neovisionaries.ws.client.SocketConnector.doConnect(SocketConnector.java:110)
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err:   ... 4 more
09-22 15:41:47.071 7682-7779/com.mobile_function.webrtc_android W/System.err: Caused by: libcore.io.ErrnoException: connect failed: EHOSTUNREACH (No route to host)
09-22 15:41:47.079 7682-7779/com.mobile_function.webrtc_android W/System.err:     at libcore.io.Posix.connect(Native Method)
09-22 15:41:47.079 7682-7779/com.mobile_function.webrtc_android W/System.err:     at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:85)
09-22 15:41:47.079 7682-7779/com.mobile_function.webrtc_android W/System.err:     at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
09-22 15:41:47.079 7682-7779/com.mobile_function.webrtc_android W/System.err:     at libcore.io.IoBridge.connect(IoBridge.java:112)
09-22 15:41:47.079 7682-7779/com.mobile_function.webrtc_android W/System.err:   ... 8 more

我已经搜索了有关这些错误代码的某些主题。我的 WiFi 连接已启用,我可以使用我的 Vuzix 玻璃通过 mozilla firefox 访问不同的网页,但我无法访问我的服务器。

这两个客户端肯定在同一个子网中: Android:192.168.179.94 WebApp 的 Html 服务器:192.168.179.36:8080 节点套接字服务器:192.168.179.36:9090 网关:192.168.179.1

我希望任何人都可以给我一些建议,我该如何解决这个问题

亲切的问候

JMD

4

1 回答 1

0

解决了问题。帮助我解决问题的链接:http: //forum.airdroid.com/discussion/379/i-can-t-even-ping-my-phone

亲切的问候约翰

于 2016-09-23T11:28:04.730 回答