Android UDP 通信。无法从设备接收数据

Posted

技术标签:

【中文标题】Android UDP 通信。无法从设备接收数据【英文标题】:Android UDP communication. Cannot receive a data from device 【发布时间】:2017-05-16 14:13:43 【问题描述】:

有一个物理设备可以使用 UDP 协议连接手机。 问题是这样的:为设备编程的电子工程师编写了一个与该设备交互的桌面程序(也使用 UDP),并且一切都在那里顺利运行:设备接收命令并发送响应,没有任何问题和异常。

但是使用手机 - 麻烦...手机通过 WiFi 连接到设备没有问题,发送命令也没有任何问题(没有超时异常),但是接收有问题 - 一旦答案到来,其他不来。一般来说socket.receive不像桌面程序那么稳定,经常会弹出timeoutexception ...

我已授予它所需的所有权限:

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

我在 AsyncTask 中运行一个命令:

private class GetStatus extends AsyncTask<byte[], Void, UdpResult> 

@Override
protected void onPreExecute() 
    super.onPreExecute();
    isPinging = true;

    if (udpSettingsListener != null) 
        udpSettingsListener.onPreGetStatus();
    


@Override
protected UdpResult doInBackground(byte[]... params) 
    UdpResult udpResult = sendCommand(params[0]);
    udpResult.opName = "GetStatus";
    udpResult.odDate = System.currentTimeMillis();
    udpResults.add(udpResult);
    return udpResult;


@Override
protected void onPostExecute(UdpResult result) 
    super.onPostExecute(result);
    isPinging = false;

    if (udpSettingsListener != null) 
        if (result.succeed) 
            udpSettingsListener.onGotStatus(new DeviceStatus(result.response));
         else 
            udpSettingsListener.onFailedToGetStatus(result.exception);
        
    

这里是与设备通信的“sendCommand”函数:

private UdpResult sendCommand(byte[] command) 
UdpResult udpResponse = new UdpResult();
try 
    Thread.sleep(sleepFor);
 catch (InterruptedException e) 
    e.printStackTrace();

do 
    udpResponse.command = command;
    udpResponse.response = new byte[BUFFER_SIZE];
    DatagramSocket socket = null;

    try 
        socket = new DatagramSocket();
        socket.setSendBufferSize(BUFFER_SIZE);
        socket.setReceiveBufferSize(BUFFER_SIZE);
        socket.setSoTimeout(timeout);
        InetAddress inetAddress = InetAddress.getByName(ipAddress);
        DatagramPacket sendPacket = new DatagramPacket(udpResponse.command, BUFFER_SIZE, inetAddress, port);
        DatagramPacket receivePacket = new DatagramPacket(udpResponse.response, BUFFER_SIZE, inetAddress, port);
        socket.send(sendPacket);
        socket.receive(receivePacket);
        udpResponse.succeed = true;
     catch (Exception e) 
        Log.e(TAG, "sendCommand: ", e);
        udpResponse.succeed = false;
     finally 
        if (socket != null) 
            socket.close();
        
    
    udpResponse.attempts++;
 while (udpResponse.attempts < maxAttempts && !udpResponse.succeed);
return udpResponse;

这是我收到的超时异常:

> java.net.SocketTimeoutException 在 > libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:598) 在 > libcore.io.IoBridge.recvfrom(IoBridge.java:556) 在 > java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:163) > 在 > java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:171) > 在 java.net.DatagramSocket.receive(DatagramSocket.java:274) 在 > com.andreyserdyuk.gaash.helpers.UdpHelper.sendCommand(UdpHelper.java:326) > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper.access 1400 美元(UdpHelper.java:27) > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:371) > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:357) > 在 android.os.AsyncTask$2.call(AsyncTask.java) 在 > java.util.concurrent.FutureTask.run(FutureTask.java:237) 在 > android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java) 在 > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) > 在 > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) > at java.lang.Thread.run(Thread.java:818) 原因: > android.system.ErrnoException:recvfrom 失败:EAGAIN(再试一次)在 > libcore.io.Posix.recvfromBytes(本机方法)在 > libcore.io.Posix.recvfrom(Posix.java:185) 在 > libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250) 在 > libcore.io.IoBridge.recvfrom(IoBridge.java:553) 在 > java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:163)* > 在 > java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:171)* > 在 java.net.DatagramSocket.receive(DatagramSocket.java:274)* 在 > com.andreyserdyuk.gaash.helpers.UdpHelper.sendCommand(UdpHelper.java:326)* > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper.access$1400(UdpHelper.java:27)* > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:371)* > 在 > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:357)* > 在 android.os.AsyncTask$2.call(AsyncTask.java)* 在 > java.util.concurrent.FutureTask.run(FutureTask.java:237)* 在 > android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java)* 在 > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)* > 在 > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)* > 在 java.lang.Thread.run(Thread.java:818)*

【问题讨论】:

也许你应该开始在一个线程上接收,然后从另一个线程发送,另外,如果由于某种原因发送的数据没有到达,设备可能永远不会发送响应 你使用哪个端口号?,只有root系统应用可以监听端口 ipAddress - 192.168.1.1,端口 - 8010 【参考方案1】:

我只能猜测您的超时在发送数据包之前就开始了。这意味着您尝试发送的数据包太大。

当你说:一旦答案来了,另一个就不来了。我不清楚。我的猜测是您收到了一个数据包,但没有收到另一个数据包。 一种快速测试是增加超时。这将确认要接收的数据包太大。 我的建议是尝试发送较小的数据包。是否在您的 Android 应用中插入了一些调试点来查找问题?

【讨论】:

BUFFER_SIZE 始终为 38 字节。它从未改变过。 38 字节数组 - 这是设备可以发送和接收的固定数据大小。 您是否尝试增加超时延迟?

以上是关于Android UDP 通信。无法从设备接收数据的主要内容,如果未能解决你的问题,请参考以下文章

在UDP Socket java android上发送和接收数据

Android UDP不接收数据

UDP有时无法接收任何内容

Android 基于UDP的Socket通信

P2921下载程序小常识

c#,socket无法接收分片的UDP数据包