java Android从不接收UDP数据包

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2101253/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:27:23  来源:igfitidea点击:

Android never receives UDP packet

javaandroidudp

提问by Stefan Steiger

The below code results in a timeout.

以下代码导致超时。

It works fine on non-Android Java. What's the matter?

它在非 Android Java 上运行良好。怎么了?

 //@Override
public static void run()
{
    //System.out.println ( "Local Machine IP : "+addrStr.toString (  )  ) ;
    HelloWorldActivity.tv.setText("Trace 1");

    try
    {
        // Retrieve the ServerName
        InetAddress serverAddr; //= InetAddress.getByName(Server.SERVERIP);
        InetAddress ias[] = InetAddress.getAllByName(Server.SERVERNAME);
        serverAddr  = ias[0];

        Log.d("UDP", "C: Connecting...");
        /* Create new UDP-Socket */
        DatagramSocket socket = new DatagramSocket();

        /* Prepare some data to be sent. */
        String strQuery="????getservers"+" "+Server.iProtocol+" "+"'all'";
        Log.d("UDP", strQuery);
        //byte[] buf = ("????getservers 68 'all'").getBytes();
        byte[] buf = strQuery.getBytes();

        /* Create UDP-packet with
         * data & destination(url+port) */
        DatagramPacket packet = new DatagramPacket(buf, buf.length,
                                                   serverAddr, Server.SERVERPORT);

        Log.d("UDP", "C: Sending: '" + new String(buf) + "'");

        /* Send out the packet */
        socket.setSoTimeout(5000);
        socket.send(packet);
        Log.d("UDP", "C: Sent.");
        Log.d("UDP", "C: Done.");

        // http://code.google.com/p/android/issues/detail?id=2917

        byte[] buffer= new byte[1024*100];
        DatagramPacket receivePacket
          = new DatagramPacket(buffer,
                               buffer.length); //, serverAddr, Server.SERVERPORT);
        socket.receive(receivePacket);
        HelloWorldActivity.tv.setText("TTT");

        String x = new String(receivePacket.getData());
        Log.d("UDP", "C: Received: '" + x  + "'");
        HelloWorldActivity.tv.setText(x);

   } catch (Exception e) {
       HelloWorldActivity.tv.setText(e.getMessage());
       Log.e("UDP", "C: Error", e);
   }
}


public class Server
{
    /*
    //public static java.lang.string SERVERIP;
    public static String SERVERNAME = "monster.idsoftware.com";
    public static String SERVERIP = "192.246.40.56";
    public static int SERVERPORT = 27950;
    public static int PROTOCOL = 68;
      */

    //public static String SERVERNAME="monster.idsoftware.com";
    public static String SERVERNAME="dpmaster.deathmask.net";

    public static String SERVERIP="192.246.40.56";
    public static int SERVERPORT=27950;
    //public static int iProtocol= 68; // Quake3
    public static int iProtocol=71; // OpenArena

}

Android manifest:

安卓清单:

<?xml version="1.0" encoding="utf-8"?>

<use-permission id="android.permission.READ_CONTACTS" />

    <use-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_GPS" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
    <uses-permission android:name="android.permission.ACCESS_CELL_ID" />

    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

<application
        android:icon="@drawable/icon"
        android:label="AAA New Application"
        >
    <activity android:name="HelloWorldActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>

回答by Dave Webb

Are you testing this on the emulator or on an actual phone? If you're using an emulator you need to be aware of how networking on the emulator works. Most specifically:

您是在模拟器上还是在实际手机上对此进行测试?如果您使用仿真器,则需要了解仿真器上的网络如何工作的。最具体的:

Each instance of the emulator runs behind a virtual router/firewall service that isolates it from your development machine's network interfaces and settings and from the internet. An emulated device can not see your development machine or other emulator instances on the network. Instead, it sees only that it is connected through Ethernet to a router/firewall.

模拟器的每个实例都在一个虚拟路由器/防火墙服务后面运行,该服务将它与开发机器的网络接口和设置以及 Internet 隔离开来。仿真设备无法在网络上看到您的开发机器或其他仿真器实例。相反,它只看到它通过以太网连接到路由器/防火墙。

You'll probably need to set up port forwarding, either using the Emulator consoleor using the adbcommand.

您可能需要使用模拟器控制台使用adb命令来设置端口转发。

回答by Elliott Hughes

UDP works fine. i don't think your server is sending a response because your outgoing packet doesn't contain the bytes you think it contains.

UDP 工作正常。我不认为您的服务器正在发送响应,因为您的传出数据包不包含您认为它包含的字节。

see my comments in the android bug you raised (http://code.google.com/p/android/issues/detail?id=6163).

在您提出的 android 错误中查看我的评论(http://code.google.com/p/android/issues/detail?id=6163)。

回答by optics

byte[] buf = new byte[256];
socket = new DatagramSocket(port);
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);

Above worked for me... Your buffer seems large?

以上对我有用......你的缓冲区似乎很大?



Might be a little far fetched but what are you trying to receive from?

可能有点牵强,但你想从什么地方得到什么?

If you are trying to communicate with a XP machine that has two network cards (one could be wired and the other wireless, any mix) and you are are using XP built in firewall?

如果您尝试与具有两个网卡(一个可以是有线的,另一个是无线的,任意组合)的 XP 机器进行通信,并且您正在使用 XP 内置的防火墙?

Then UDP requests are only listened for on the first network on the computer, disable other network cards on your system, only have enabled the one that your trying to talk your Android device to.

然后 UDP 请求仅在计算机上的第一个网络上侦听,禁用系统上的其他网卡,仅启用您尝试与 Android 设备通话的网卡。

回答by Hunter D

To send/broadcast UDP using socket.send(), you need the android permission:

要使用 socket.send() 发送/广播 UDP,您需要 android 权限:

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />

However, even so, socket.receive() doesn't seem to catch the broadcast, even when run in the same context. I wonder if there's another permission for socket.receive()?...

然而,即便如此,socket.receive() 似乎也没有捕捉到广播,即使在相同的上下文中运行时也是如此。我想知道 socket.receive() 是否还有其他权限?...