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 通信。无法从设备接收数据的主要内容,如果未能解决你的问题,请参考以下文章