监听数据报套接字与任何IP和任何端口号android

时间:2016-10-18 16:08:10

标签: android sockets broadcast datagram socket-timeout-exception

您好我使用具有特定端口号的DatagramSocket发送广播。它成功发送消息。但是当我用open IP地址和任何端口号监听接收消息时,它会抛出sockettimeoutexception。但我与同一网络连接。

//清单

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<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.WRITE_EXTERNAL_STORAGE" />

//全局定义端口号

int PORT=2739;

//启动异步任务

new MyClientTask().execute();

///异步任务

public class MyClientTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... arg0) {

            new PacketSender().run();
            new PacketReceiver().run();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);


        }

    }

这是我的发送请求

public class PacketSender implements Runnable {
        @Override
        public void run() {
            DatagramSocket sendSoc = null;
            try {
                sendSoc = new DatagramSocket();
                sendSoc.setBroadcast(true);
                sendSoc.setSoTimeout(5000);
                sendSoc.setReuseAddress(true);
                byte[] ip = prop.ToBuffer();
                DatagramPacket packet = new DatagramPacket(ip,
                        ip.length, getBroadcastIp(), PORT);
                Log.d("Sending", packet.getAddress().getHostAddress() + " " + packet.getPort());
                sendSoc.send(packet);
                sendSoc.close();
            } catch (IOException e) {
                Log.d("Send", "IOException");
                e.printStackTrace();
                if (sendSoc != null)
                    sendSoc.close();
            }
        }
    }

这是我的倾听请求

public class PacketReceiver implements Runnable {
        @Override
        public void run() {
            DatagramSocket receiveSoc = null;
            try {
              //here 0 represent any port number including system reserved port number
                receiveSoc = new DatagramSocket(0, InetAddress.getByName("0.0.0.0"));  
                receiveSoc.setBroadcast(false); //also tried with true
                receiveSoc.setSoTimeout(5000);  //alse tried with removing timeout value

                int i = 0;
                while (true) {
                    Log.d("data value", " " + i);
                    i++;
                    byte buf[] = new byte[1024];
                    DatagramPacket pack = new DatagramPacket(buf, buf.length);

                    try {
                        receiveSoc.receive(pack);

                        String message = new String(pack.getData()).trim();
                        Log.i("test", message + " server ip : " + pack.getAddress().getHostAddress());

                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                }
            } catch (SocketTimeoutException e) {
                Log.d("Main", "SocketTimeoutException");
                e.printStackTrace();
                receiveSoc.close();
                new PacketReceiver().run();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                Log.d("Response", "IOException");
                e.printStackTrace();
            }
        }
    }

//获取广播ip

public InetAddress getBroadcastIp() throws IOException {
        DhcpInfo dhcp = myWifiManager.getDhcpInfo();
        int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
        byte[] quads = new byte[4];
        for (int k = 0; k < 4; k++)
            quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
        return InetAddress.getByAddress(quads);
    }

除了我想要通信的硬件之外,它能够从LAN中的所有主机接收广播消息。我可以向它发送广播。但是我无法接收来自这个特定设备的广播。

2 个答案:

答案 0 :(得分:0)

对您的代码进行以下更改:

public class PacketSender implements Runnable {

    @Override
    public void run() {

        // ...

        DatagramPacket packet = new DatagramPacket(ip,
                ip.length, InetAddress.getByName("255.255.255.255"), PORT);

        // ...
    }
}
public class PacketReceiver implements Runnable {

    @Override
    public void run() {

        // ...

        receiveSoc = new DatagramSocket(PORT, InetAddress.getByName("0.0.0.0"));

        // ...
    }
}

<强>更新

MyClientTask代码无法正常工作,因为它会依次调用发件人和收件人。发送者将发送给任何人,接收者将永远等待没有消息。当接收者已经在收听数据报时,你必须给发送者打电话。

所以,而不是

new MyClientTask().execute();

你想要像

这样的东西
new Thread(new PacketReceiver()).start();

// Just to make sure that the receiver has started up.
// You'll want to do a different kind of synchronization.
SystemClock.sleep(50);

new Thread(new PacketSender()).start();

答案 1 :(得分:0)

我从下面解决了这个问题。网络中的数据包转发没有问题。我在setBroadcast值为true的同一套接字对象上发送和接收广播。因此套接字发送广播并监听来自同一广播的任何广播。您不应该使用不同的套接字对象进行侦听广播。我很晚才明白。

public class PacketSender extends Thread {
        @Override
        public void run() {
            DatagramSocket sendSoc = null;
            try {
                sendSoc = new DatagramSocket();
                sendSoc.setBroadcast(true);
                InetSocketAddress  address = new InetSocketAddress(getBroadcastQuadIp(), PORT);

                byte[] ip = prop.ToBuffer();
                DatagramPacket packet = new DatagramPacket(ip,
                        ip.length, address.getAddress(), address.getPort());


                sendSoc.send(packet);    

                //////////// receiver begin
                int i = 0;
                while (true) {

                    i++;

                    final byte buf[] = new byte[1024];
                    final DatagramPacket pack = new DatagramPacket(buf, buf.length);
                    try {
                        sendSoc.receive(pack);

                        String message = new String(pack.getData()).trim();

                        Log.i("test", message + " server ip : " + pack.getAddress().getHostAddress());

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

                    }
                }
            } catch (IOException e) {
                Log.d("Send", "IOException");
                e.printStackTrace();
                if (sendSoc != null)
                    sendSoc.close();
            }
        }
    }