有一个物理设备可以使用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 at > libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:598) at > libcore.io.IoBridge.recvfrom(IoBridge.java:556) at > java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:163) > at > java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:171) > at java.net.DatagramSocket.receive(DatagramSocket.java:274) at > com.andreyserdyuk.gaash.helpers.UdpHelper.sendCommand(UdpHelper.java:326) > at > com.andreyserdyuk.gaash.helpers.UdpHelper.access$1400(UdpHelper.java:27) > at > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:371) > at > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:357) > at android.os.AsyncTask$2.call(AsyncTask.java) at > java.util.concurrent.FutureTask.run(FutureTask.java:237) at > android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java) at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) > at java.lang.Thread.run(Thread.java:818) Caused by: > android.system.ErrnoException: recvfrom failed: EAGAIN (Try again) at > libcore.io.Posix.recvfromBytes(Native Method) at > libcore.io.Posix.recvfrom(Posix.java:185) at > libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:250) at > libcore.io.IoBridge.recvfrom(IoBridge.java:553) at > java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:163)* > at > java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:171)* > at java.net.DatagramSocket.receive(DatagramSocket.java:274)* at > com.andreyserdyuk.gaash.helpers.UdpHelper.sendCommand(UdpHelper.java:326)* > at > com.andreyserdyuk.gaash.helpers.UdpHelper.access$1400(UdpHelper.java:27)* > at > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:371)* > at > com.andreyserdyuk.gaash.helpers.UdpHelper$SetRtc.doInBackground(UdpHelper.java:357)* > at android.os.AsyncTask$2.call(AsyncTask.java)* at > java.util.concurrent.FutureTask.run(FutureTask.java:237)* at > android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java)* at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)* > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)* > at java.lang.Thread.run(Thread.java:818)*
答案 0 :(得分:0)
我只能猜测你的超时会在数据包发送之前启动。这意味着您尝试发送的数据包太大。
当你说:一旦答案到来,另一个不会来。我不清楚。我的猜测是你收到一个数据包,但没有收到另一个数据包。 一个快速测试是增加超时。这将确认要接收的数据包太大。 我的建议是尝试发送较小的数据包。在Android应用程序中插入一些调试点来查找问题?