我正在实施一个发现过程:
第一个电话有效。但其他调用会出现绑定错误。已在使用的地址:绑定
我正在运行Windows 7。我做了一些测试,发现在channel.close()之后,Netstat仍然提供:
netstat -a -b -sp udp \ grep 55224
UDP 0.0.0.0:55224
因此,udp端口仍然在OS级别打开。
我搜索了网络,这可能是os级的漏洞:Some java Datagram Socket questions。
我运行了两个测试,一个使用NIO通道,另一个不使用(来自web上的测试)。我在NIO版本中重复我的错误,但是如果我不使用NIO,它就会工作。
任何人都可以告诉我如何使它与NIO一起工作。目标平台是Android,我不想总是听广播,但只听一段重复的时间。
测试插座
public void testConnectCloseWithSocket() {
long tCumulative = 0;
int errAt = -1;
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
try {
errAt = i;
DatagramSocket result = new DatagramSocket(null);
result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
result.close();
//success at last
tCumulative = 0;
} catch (Exception e) {
System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());
tCumulative+=50;
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
}
i--;
}
}
System.out.println("end...");
}结果SOCKET<
开始..。错误(at=1319) (waited=0ms):已在使用的地址:无法绑定
错误(at=1438) (waited=0ms):已在使用的地址:无法绑定
错误(at=1587) (waited=0ms):已在使用的地址:无法绑定
错误(at=1740) (waited=0ms):已在使用的地址:无法绑定
结束..。
我确实犯了一些错误,但是插座被正确关闭了.可以满足我的需要
用通道测试
public void testConnectCloseWithChannel() {
long tCumulative = 0;
int errAt = -1;
System.out.println("start...");
for (int i = 0; i < 4000; i++) {
try {
errAt = i;
Selector selector = Selector.open();
DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(true);
channel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
clientKey.cancel();
channel.close();
//success at last
tCumulative = 0;
} catch (Exception e) {
System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());
tCumulative+=50;
try {
Thread.sleep(tCumulative);
} catch (InterruptedException e1) {
}
i--;
}
}
System.out.println("end...");
}注意:对channel.register进行了注释,测试工作。
结果与渠道
开始..。错误(at=0) (waited=0ms):空错误(at=0) (waited=50ms):已经使用的地址:绑定
错误(at=0) (waited=100ms):已在使用的地址:绑定
错误(at=0) (waited=150ms):地址已在使用:绑定.
谢谢你的帮助
发布于 2012-10-19 15:14:16
我确实犯了一些错误,但是插座被正确关闭了.可以满足我的需要
不,如果您有错误,您的通道没有正确关闭。
您必须在close块的finally子句中执行try。
Selector selector = Selector.open();
try
{
DatagramChannel channel = DatagramChannel.open();
try
{
channel.configureBlocking(true);
channel.socket().bind(
new InetSocketAddress(InetAddress.getLocalHost(), 9005)
);
SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
clientKey.cancel();
}
finally
{
channel.close();
}
}
finally
{
selector.close( )
}发布于 2012-10-19 21:17:21
如果通道已在Selector中注册,则通道关闭的某些部分将推迟到下一个select()。它被记录在Selector,AbstractSelector,SelectorSpi,SelectableChannel,AbstractSelectableChannel森林的某个地方,在那里,当我需要它时,我永远找不到它。如果关闭通道时处于select循环和线程中,则可以通过调用selectNow()使其立即生效。
https://stackoverflow.com/questions/12977164
复制相似问题