getSocketAddress() 方法会导致延迟,从而导致 Android 中的通信滞后
我正在开发一个 UDP 响应器来处理基本的 SSDP 命令。这段代码的目的是进行自动发现,因此当服务器向特定组发送多播时,所有其他订阅设备都应该发回一个 UDP 数据包,向发送多播的主机和端口宣布其存在。我的 Android 设备接收和发送数据包都很好,但由于从 getSocketAddress() 方法返回 SocketAddress 对象需要很长时间,因此服务器超时,关闭侦听端口,并且永远不会从 Android 设备取回数据包。
这是我的代码:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MulticastSocket ms = null;
byte[] packBuf = new byte[128];
try {
ms = new MulticastSocket(32410);
ms.joinGroup(InetAddress.getByName("239.255.255.250"));
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
while (true)
{
DatagramPacket receivedPack = new DatagramPacket(packBuf, packBuf.length);
try {
ms.receive(receivedPack);
Log.d(TAG, "Received data");
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
String responseStr = "HTTP/1.0 200 OK\n" +
"Content-Type: app\n" +
"Resource-Identifier: 945e7dd5913ab45f1db4f271a1620b9471fb7d4d\n" +
"Name: Test App\n" +
"Port: 8888\n" +
"Updated-At: 1319511680\n" +
"Version: 0.9.3.4-29679ad\n" +
"Content-Length: 23\n\n" +
"<message>test</message>";
byte[] response = responseStr.getBytes();
DatagramSocket sendSocket = null;
try {
sendSocket = new DatagramSocket();
} catch (IOException e2) {
// TODO Auto-generated catch block
Log.e(TAG,"Erro",e2);
}
DatagramPacket outPack;
try {
outPack = new DatagramPacket(response, responseStr.length(), receivedPack.getSocketAddress());
sendSocket.send(outPack);
} catch (UnknownHostException e1) {
Log.e(TAG,"Erro",e1);
}
catch (IOException e) {
Log.e(TAG,"Erro",e);
}
catch (Exception e)
{
Log.e(TAG,"Erro",e);
}
}
}
有什么想法吗?
预先感谢,
fbr
I'm developing a UDP responder to handle basic SSDP commands. The purpose of this piece of code is to do auto discovery, so when the server sends a multicast to a specific group all other subscribed devices should send back a UDP packet announcing its presence to the host and port of who sent the multicast. My android device receives and sends the packet just fine but because it takes too long to get back the SocketAddress object from getSocketAddress() method the server times out, closes the listening port and never gets a packet back from the android device.
Here's my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MulticastSocket ms = null;
byte[] packBuf = new byte[128];
try {
ms = new MulticastSocket(32410);
ms.joinGroup(InetAddress.getByName("239.255.255.250"));
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
while (true)
{
DatagramPacket receivedPack = new DatagramPacket(packBuf, packBuf.length);
try {
ms.receive(receivedPack);
Log.d(TAG, "Received data");
} catch (IOException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
String responseStr = "HTTP/1.0 200 OK\n" +
"Content-Type: app\n" +
"Resource-Identifier: 945e7dd5913ab45f1db4f271a1620b9471fb7d4d\n" +
"Name: Test App\n" +
"Port: 8888\n" +
"Updated-At: 1319511680\n" +
"Version: 0.9.3.4-29679ad\n" +
"Content-Length: 23\n\n" +
"<message>test</message>";
byte[] response = responseStr.getBytes();
DatagramSocket sendSocket = null;
try {
sendSocket = new DatagramSocket();
} catch (IOException e2) {
// TODO Auto-generated catch block
Log.e(TAG,"Erro",e2);
}
DatagramPacket outPack;
try {
outPack = new DatagramPacket(response, responseStr.length(), receivedPack.getSocketAddress());
sendSocket.send(outPack);
} catch (UnknownHostException e1) {
Log.e(TAG,"Erro",e1);
}
catch (IOException e) {
Log.e(TAG,"Erro",e);
}
catch (Exception e)
{
Log.e(TAG,"Erro",e);
}
}
}
Any ideas?
thanks in advance,
fbr
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最可能的问题是
getSocketAddress()
正在尝试解析 IP 地址的 DNS 名称,该 IP 地址由于是多播地址或只是一般 DNS 延迟而超时。InetSocketAddress
类有一个构造函数选项needResolved
可以控制此行为。不幸的是,DatagramPacket.getSocketAddress()
似乎不允许您指定希望将该值设置为 false。这显然是一个已知问题,最近对此进行了一些讨论:
问题 12328:DatagramChannel - 在不查找主机名的情况下无法接收
表明这个问题已在 Android 3.0 中修复,并为 Android 2.0 提供了一些可能有效或无效的解决方法。
在您的情况下,您可以尝试创建一个设置为 INADDR_ANY 的
InetSocketAddress
和端口 0,并将needsResolved
设置为 0,然后在创建receivedPack
时将其传入代码>.希望receive()
能够重用它并记住该设置。The most likely problem is that
getSocketAddress()
is trying to resolve the DNS name of the IP address, which is timing out either due to it being a multicast address or just general DNS lag.The
InetSocketAddress
class has a constructor optionneedResolved
which can control this behavior. Unfortunately, it does not appear thatDatagramPacket.getSocketAddress()
allows you to specify that you want that set to false.This is apparently a known issue, with some recent discussion of it here:
Issue 12328: DatagramChannel - cannot receive without a hostname lookup
The thread suggests that this has been fixed in Android 3.0, and offers a couple of workarounds for Android 2.0 which may or may not work.
In your case, you could try creating an
InetSocketAddress
set to INADDR_ANY and port 0 withneedsResolved
set to 0, and then pass that in when you createreceivedPack
. Hopefullyreceive()
will reuse that and remember the setting.我想到了 2 件事...
2)时会发生什么:
1) 当您更改为
我记得在家庭自动化系统上的嵌入式 Java 中遇到过此类问题。我们的短期解决方案是将大部分机器和多播地址放入主机文件中。从长远来看,我们最终得到了本地 DNS 服务器。
Java 网络堆栈中的某处有一个参数,告诉它在内存中缓存 DNS 故障多长时间。我想,我们把这个数字从 10 秒提高到了 5 分钟。
2 things come to mind...
1) What happens when you change:
to
2) I remember having this sort of problem with an embedded Java on a Home Automation system. Our short term solution was to put most of the machine and multicast addresses in the hosts file. Long term we ended up with a local DNS server.
There is a parameter somewhere in the Java Network stack that tells it how long to cache DNS failures in memory. We cranked that number up to, I think, 5 minutes instead of 10 seconds.