gpt4 book ai didi

java - 带有 OSGi : Bundle stopped, 套接字的套接字仍然打开

转载 作者:行者123 更新时间:2023-11-29 06:38:20 25 4
gpt4 key购买 nike

我在使用我的一个 bundle 中的 ServerSocket 时遇到了这个问题,我们就称它为:FooBundle

这个 FooBundle 有一个 SocketListener.java 类。此类是一个线程,为了对其进行一些概述,我将粘贴一些伪代码:

public class SocketListener implements Runnable{

ServerSocket providerSocket;
Socket connection = null;
private boolean closeIt = false;

public void run() {
try {
//Create the server socket
providerSocket = new ServerSocket(41000, 10);
} catch (IOException e1) {
//catching the exception....
}
while(!closeIt){
try{
connection = providerSocket.accept();
in = new Scanner(new InputStreamReader(onnection.getInputStream()));
while(in.hasNext() !=false)
message = message + " "+in.next();
// bla bla bla...
} catch (IOException e) {
//bla bla...
}
finally{
try{
if (message.equalsIgnoreCase("bye"))
providerSocket.close();
closeIt = true;
}
catch(IOException ioException){
//........
}
}

如您所见,这是一个简单的线程,它等待连接,直到它从 SocketClients 之一接收到的消息是“再见”

这就是我现在面临的问题:当 Bundle 停止时,我确实需要重新启动整个 OSGi 框架 :如果我尝试重新启动 bundle ,则会抛出一条 java.net.BindException 消息:“Address already in use”。因此,我停止了 bundle ,但套接字尚未关闭。

在 OSGi 中,您需要注意 Activator 中的 stop() 方法必须包含的内容,但我不能传递任何匿名引用线程到激活器。

想象一下,这是我在包中的类图:

**FooBundle**
|__FooBundleActivator
|__FooImpl
|__SocketListener (thread)

SocketListener 线程作为匿名线程FooImpl 类调用。

我的问题是:在 OSGi 范例中是否有任何适当的方法来控制匿名线程,特别是在我的情况下,非关闭套接字端口?

提前致谢。

最佳答案

如果您的 bundle 被告知停止,那么假设停止的人知道他在做什么。是的,你的协议(protocol)期待“再见”,但狗屎发生了,任何有这些问题的协议(protocol)对于现实世界来说都太脆弱了。一般来说,OSGi 中的所有任务都应该有一个生命周期。这就是我的代码(使用 DS 而不是激活器)。

@Component
public class ProtocolServer extends Thread {
volatile ServerSocket server;
volatile Socket connection;

public ProtocolServer() {
super("Protocol Server on 4100"); // to identify the thread
}

@Activate void activate() {
setDaemon(true);
start();
}

@Deactivate void deactivate() {
interrupt();

// best effort close (even if null)
try { server.close(); } catch(Exception e) {}
try { connection.close(); } catch(Exception e) {}

join(10000); // waits 10 secs until thread exits
}

public void run() {
// loop for active component
while( !isInterrupted() )
try {
doServer();
} catch( Exception e) {
log(e);

// bad error, accept failed or bind failed
// or server socket was closed. If we should remain
// active, sleep to prevent overloading the
// system by trying too often, so sleep

if ( !isInterrupted() )
try { Thread.sleep(5000); } catch(Exception e) {}
}
}

private void doServer() throws Exception {
server = new ServerSocket(4100)
try {
while( !isInterrupted() )
doConnection(server);
} finally {
server.close();
}
}

private void doConnection(ServerSocket server) throws Exception {
connection = server.accept();
try {
doMessages(connection);

// the pseudo code exits here, but that seems
// kind of weird? If desired, interrupt
// this object, this will exit the thread

} catch( Exception e) {
log(e); // the connection failed, is not uncommon
} finally {
connection.close();
connection = null;
}
}

private void doMessages(Socket connection) {
MyScanner s = new MyScanner(socket);
String msg;
while( !isInterrupted() && !"bye".equals( msg=s.getMessage()))
process(msg);
}
}

OSGi 中的一个重要设计考虑因素是组件即使出现故障也能继续工作。在网络中,您经常会遇到自行消失的 transient 错误。即使他们不这样做,也希望服务器在您解决问题时继续尝试。您的伪代码在实践中将是一场噩梦,因为它会在任何错误时消失。任何具有多个此类组件的系统往往会很快变得不稳定。

同样让我吃惊的是,您一次只支持一个连接。一般来说,最好不要限制它并在自己的线程中处理消息。在这种情况下,您必须确保为连接创建的每个处理程序也已适当关闭。

关于java - 带有 OSGi : Bundle stopped, 套接字的套接字仍然打开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16673555/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com