Android 模拟器无法从套接字接收数据但相同的代码在 Genymotion 中工作

Android Emulator not able to receive data from socket but same code works in Genymotion

我正在通过 Java 套接字客户端从我的开发机器 (Mac) 向充当套接字服务器的 android 模拟器发送数据。所以基本上我首先启动 android 程序,它打开套接字端口并等待数据。

onStart 调用两个函数,一个是获取 IP,另一个是打开服务器套接字

  @Override
    protected void onStart() {
        super.onStart();

        getDeviceIpAddress();

        new Thread(new start_siddhi_server()).start();

    } //onStart

用于获取 IP 的代码是

public void getDeviceIpAddress() {
    try {
        //Loop through all the network interface devices
        for (Enumeration<NetworkInterface> enumeration = NetworkInterface
                .getNetworkInterfaces(); enumeration.hasMoreElements(); ) {
            NetworkInterface networkInterface = enumeration.nextElement();
            //Loop through all the ip addresses of the network interface devices
            for (Enumeration<InetAddress> enumerationIpAddr = networkInterface.getInetAddresses(); enumerationIpAddr.hasMoreElements(); ) {
                InetAddress inetAddress = enumerationIpAddr.nextElement();
                //Filter out loopback address and other irrelevant ip addresses
                if (!inetAddress.isLoopbackAddress() && inetAddress.getAddress().length == 4) {
                    //Print the device IP address into the text view

                    Log.d("ip address", inetAddress.getHostAddress());


                }
            }
        }
    } catch (SocketException e) {
        Log.e("ERROR:", e.toString());
    }
}

用于启动服务器套接字的代码是

class start_siddhi_server implements Runnable {

    @Override
    public void run() {


        Log.d("E", "starting siddhi server.........");

        // Creating Siddhi Manager
        SiddhiManager siddhiManager = new SiddhiManager();


        String definition1 = " define stream temprature (room_no string, temp int);";

        String query1 = "@info(name = 'query1') from temprature[temp >= 10] " +
                "select room_no, temp  " +
                "insert into myOutputStream; ";


        //Generating runtime

        SiddhiAppRuntime siddhiAppRuntime = siddhiManager.createSiddhiAppRuntime(definition1 + query1);

        //Adding callback to retrieve output events from query

        siddhiAppRuntime.addCallback("myOutputStream", new StreamCallback() {
            @Override
            public void receive(Event[] events) {

                // for loop for iterating each event
                for (Event event : events) {

                    Log.d("complex event = ", "  Temp is " + event.getData(1));

                } //end of for

            } // end of receive method
        });  // end of callback

        // getting input handler
        InputHandler inputHandlerA = siddhiAppRuntime.getInputHandler("temprature");

        // starting siddhi app
        siddhiAppRuntime.start();

        // starting server socket
        ServerSocket serverSocket = null;

        try {
            serverSocket = new ServerSocket(7000);
        } catch (IOException e) {
            e.printStackTrace();
        }
        Socket socket = null;

        Log.d("E", " Siddhi server is waiting for sensor data.........");


        while (true) {

            try {
                socket = serverSocket.accept();

            } catch (IOException e) {
                e.printStackTrace();
            }

            if (socket.isConnected() == true) {


                Log.d("E", "connection is successful........");

                InputStreamReader isReader = null;
                try {
                    isReader = new InputStreamReader(socket.getInputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                BufferedReader input = new BufferedReader(isReader);

                String line;

                try {
                    while ((line = input.readLine()) != null) {


                        String[] tupleData = line.split(",");

                        String[] sensor_value = new String[10];

                        int i = 0;

                        for (String tuple : tupleData) {
                            String[] tupleValue = tuple.split("=");

                            sensor_value[i] = tupleValue[1];
                            i += 1;


                        }// key pair of tuple ends

                        Integer patient_id = Integer.valueOf(sensor_value[0]);
                        Integer sensor_id = Integer.valueOf(sensor_value[1]);
                        Integer uid = Integer.valueOf(sensor_value[2]);
                        Long egtl = Long.valueOf(sensor_value[3]);

                        Long edtl = 0L;
                        //  Long edtl = Long.valueOf(sensor_value[4]);
                        Integer value = Integer.valueOf(sensor_value[4]);

                        inputHandlerA.send(new Object[]{uid, value});

//                        Log.d("patient_id = ", String.valueOf(patient_id));
//                        Log.d("sensor_id = ", String.valueOf(sensor_id));
//                        Log.d("uid = ", String.valueOf(uid));
//                        Log.d("egtl = ", String.valueOf(egtl));

                    }//while
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            } //socket.isConnected()

        } //while (true)

    } //run
} // runnig_server

此外,清单文件中的权限是

 <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--The Paho Android Service needs the following permissions to work-->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

案例 1 .

当我 运行 它使用模拟器时,我得到以下 IP

10.0.2.15

ifconfig的结果也是一样

generic_x86:/ $ ifconfig eth0
eth0      Link encap:UNSPEC    Driver virtio_net
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0 
          inet6 addr: fe80::5054:ff:fe12:3456/64 Scope: Link
          inet6 addr: fec0::5054:ff:fe12:3456/64 Scope: Site
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3565 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:4068 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:1190457 TX bytes:971370 

但问题是我无法将数据发送到此端口。

我试过跟随IP

10.0.2.1
10.0.2.2
10.0.2.15
localhostip

案例 2 .

但是当我 运行 在 Genymotion 中使用相同的代码时,我得到以下结果

IP address: 192.168.56.101

当我向这个 IP 发送数据时,它工作正常。


我做错了什么?

如何让它在 android 模拟器上运行?

我想使用 e android 模拟器,因为它是免费的

编辑 1

问题已通过端口转发解决

 adb forward tcp:7000 tcp:7000

现在的问题是,如果我使用的是模拟器,我将无法在分析器中看到网络数据

但如果我使用 Genymotion,我可以看到网络数据

你应该添加端口转发

adb forward tcp:7000 tcp:7000

然后使用localhost:7000将数据从您的计算机发送到模拟器。

原因是模拟器创建了一个私有虚拟网络 (10.0.2.0),它不是 bridged,所以为了能够访问它,您必须转发端口。