在打开移动数据时在 WiFi 网络上连接具有静态 IP 的套接字

Connecting a socket with static IP on a WiFi network while mobile data is turned on

我需要在 Android 中设计一个应用程序,它需要 phone 通过打开套接字连接到服务器。当我刚连接到特定的 wifi 网络(即托管服务器的 Wifi 网络)时,我能够实现这一点,但是在我连接到 wifi 网络和移动数据网络的情况下,我得到一个套接字异常抛出作为android 尝试通过移动网络连接套接字

刚连接到需要建立socket连接的设备的wifi时,我已经能够连接设备了

  static class StartTCPconnection extends AsyncTask<Void, Void, Void> {
    final WeakReference<RemoteActivity> activity;

    StartTCPconnection(WeakReference<RemoteActivity> activity) {
        this.activity = activity;
    }


    @Override
    protected Void doInBackground(Void... voids) {
        try {
            socket = new Socket("192.168.4.1", 900);
            Log.d(TAG, "is socket connected ? ...." + socket.isConnected());
            printWriter = new PrintWriter(socket.getOutputStream(), true);
            Log.i(TAG, "Checking if socket is really connected " + (socket.getLocalSocketAddress()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if (socket != null) {
            if (socket.isConnected() && isWifi) {
                Log.d(TAG, "onPostExecute: " + socket.isConnected());
                Toast.makeText(activity.get(), "Connection established", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "onPostExecute: " + activity.get().getSharedPreferences(Constants.REMOTE_SWITCH_SHARED_PREFERENCE, Context.MODE_PRIVATE).getInt(Constants.REMOTE_SWITCH_KEY, 99));
                if (activity.get().getSharedPreferences(Constants.REMOTE_SWITCH_SHARED_PREFERENCE, Context.MODE_PRIVATE).getInt(Constants.REMOTE_SWITCH_KEY, 1) == 1) {
                    activity.get().joyStickFragment.checkSocketInstance(socket);
                    activity.get().joyStickFragment.changeUIForConnect();
                } else if (activity.get().getSharedPreferences(Constants.REMOTE_SWITCH_SHARED_PREFERENCE, Context.MODE_PRIVATE).getInt(Constants.REMOTE_SWITCH_KEY, 1) == 2) {
                    Log.e(TAG, "onPostExecute:Check  " + socket.isConnected());
                    activity.get().buttonRemoteFragment.checkSocketInstance(socket);
                    activity.get().buttonRemoteFragment.changeUIForConnect();
                }
                activity.get().connectionIndicatorImage.setImageResource(R.drawable.avishkaar_logo_on);
                activity.get().wifiIndicator.setImageResource(R.drawable.wifi_connected_icon);
            }

        } else {
            //   Toast.makeText(activity.get(), "Wrong Wifi Network connected", Toast.LENGTH_SHORT).show();
        }

    }
}

如果唯一可用的网络是设备的 WiFi 并且移动网络已关闭,上述代码会将我连接到插座

从编程的角度来看,连接到本地网络中的服务器和不连接到本地网络中的服务器之间没有什么特别之处。唯一的要求是服务器首先实际上是可访问的,即不在无法访问的私有网络中,也没有被防火墙或类似的东西阻止。当然,服务器的 public 可达地址用作程序中的目标。

        socket = new Socket("192.168.4.1", 900);

192.168.4.1 是 private network 中的一个地址。这意味着无法从互联网访问它,这也意味着如果您使用移动数据连接或在不同网络(如 public 热点)中使用 wifi,则无法访问它。

要从这个专用网络外部建立连接,服务器必须可以从这个网络外部访问,即需要有一个 public 可路由的 IP 地址。如果服务器在一些典型的家庭网络中,这可以通过 port forwarding in the router. For larger setups such servers are located at data centers directly reachable from the internet or (as a special case of this) in the cloud.

来实现