Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带OSGi的套接字:捆绑已停止,套接字仍处于打开状态_Java_Sockets_Osgi - Fatal编程技术网

Java 带OSGi的套接字:捆绑已停止,套接字仍处于打开状态

Java 带OSGi的套接字:捆绑已停止,套接字仍处于打开状态,java,sockets,osgi,Java,Sockets,Osgi,在我的一个bundle中使用ServerSocket时,我面临着这个问题,我们把它称为:FooBundle 这个FooBundle还有一个SocketListener.java类。这个类是一个线程,为了对它做一点概述,我将粘贴一些伪代码: public class SocketListener implements Runnable{ ServerSocket providerSocket; Socket connection = null; private boolean closeIt =

在我的一个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){
        //........
         }
}
正如您所看到的,它是一个简单的线程,等待连接,直到它从一个SocketClient接收到的消息是bye

这就是我现在面临的问题:当捆绑包停止时,我确实需要重新启动整个OSGi框架:如果我尝试重新启动捆绑包,将抛出一条java.net.BindException消息:地址已在使用中。因此,我停止了捆绑,但插座尚未关闭

在OSGi中,您需要注意Activator中的stop方法必须包含哪些内容,但我无法将匿名线程的任何引用传递给Activator

假设这是捆绑包中的类图:

**FooBundle**
|__FooBundleActivator
|__FooImpl
|__SocketListener (thread)
SocketListener线程作为匿名线程从FooImpl类调用

我的问题是:在OSGi范式中,有没有合适的方法来控制匿名线程,特别是在我的例子中,控制非关闭套接字端口


提前感谢。

在退出线程功能之前,无论消息如何,您都需要关闭侦听套接字。那么,对您来说真正有区别的是,在旧连接处于超时状态时,调用该套接字以允许绑定端口


并且,请在代码中使用更好的缩进技术…

在退出线程函数之前,无论消息如何,您都需要关闭侦听套接字。那么,对您来说真正有区别的是,在旧连接处于超时状态时,调用该套接字以允许绑定端口


另外,请在代码中使用更好的缩进技术…

在Activator外部实例化ServerSocket,并通过构造函数将其传递给SocketListener。您可以在激活器的stop函数中调用serverSocket.stop


如果调用ServerSocket.stop,将抛出SocketException,它是IOException的子类。请考虑在while迭代中处理IOException,这样它肯定会停止执行迭代。

在激活器外部实例化ServerSocket,并通过构造函数将其传递给SocketListener。您可以在激活器的stop函数中调用serverSocket.stop


如果调用ServerSocket.stop,将抛出SocketException,它是IOException的子类。请考虑在while迭代中处理IOException,以确保它将停止执行迭代。

如果您的包被告知停止,那么假设停止的人知道他在做什么。是的,你的协议期待着“再见”,但是狗屎发生了,任何与这些东西有问题的协议对于现实世界来说都太脆弱了。通常,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中一个重要的设计考虑是,即使出现故障,组件也会继续工作。在网络中,经常会出现暂时性错误,这些错误会自行消失。即使他们不这样做,在您修复问题的同时,服务器继续尝试也是可取的。您的伪代码在实践中将是一场噩梦,因为它会在任何错误时消失。任何具有多个此类组件的系统都会很快变得不稳定


还有一件事让我感到惊讶,那就是您一次只支持一个连接。一般来说,最好不要对此进行限制,而是在自己的线程中处理消息。在这种情况下,您必须确保为连接创建的每个处理程序也被适当地关闭。

如果您的包被告知停止,那么假设停止的人知道他在做什么。是的,你的协议期待着“再见”,但是狗屎发生了,任何与这些东西有问题的协议对于现实世界来说都太脆弱了。通常,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中一个重要的设计考虑是,即使出现故障,组件也会继续工作。在网络中,经常会出现暂时性错误,这些错误会自行消失。即使他们不这样做,在您修复问题的同时,服务器继续尝试也是可取的。您的伪代码在实践中将是一场噩梦,因为它会在任何错误时消失。任何具有多个此类组件的系统都会很快变得不稳定

还有一件事让我感到惊讶,那就是您一次只支持一个连接。一般来说,最好不要对此进行限制,而是在自己的线程中处理消息。在这种情况下,您必须确保为连接创建的每个处理程序也相应地关闭p> 谢谢你的回答,尼古拉。然而,将ReuseAddress参数设置为true并不能真正解决这个问题,因为我仍然得到相同的绑定异常。我的线程需要一直处于活动状态,直到消息bye到达,没有任何其他可能的情况,它必须继续运行。OSGi捆绑包的问题在于,您可以随时手动停止它们。如果停止此特定捆绑,则套接字不会自行关闭。哦,很抱歉缩进,只是手动编写了伪代码:S.+1以获取帮助您无法重新绑定同一套接字。您必须关闭它并创建一个新端口,或者停止对其调用accept,稍后再继续。问题是我无法创建一个新端口,因为我有许多客户端正在转发到此特定端口。现在的解决方案是停止整个OSGi框架,这对我的应用程序来说不是很好。应该有任何类型的方法来控制匿名线程在捆绑包中的行为,但是我找不到合适的解决方案。我不熟悉这个框架。在开始/停止事件时,是否有来自it的任何挂钩/回调?我认为您需要重写一些函数,在这些函数中您可以创建/关闭套接字。注意,这些可能在不同的线程上。你是对的,套接字不会自动关闭。你认为OSGi会为你免费处理这件事吗??在bundle的start方法中创建的任何内容都必须在stop方法中清除。这包括您打开的任何套接字、启动的任何线程等。这是您作为捆绑包作者的责任,而不是其他任何人的责任。如果你需要重组你的代码使之成为可能,那就这样吧。谢谢你的回答Nikolai。然而,将ReuseAddress参数设置为true并不能真正解决这个问题,因为我仍然得到相同的绑定异常。我的线程需要一直处于活动状态,直到消息bye到达,没有任何其他可能的情况,它必须继续运行。OSGi捆绑包的问题在于,您可以随时手动停止它们。如果停止此特定捆绑,则套接字不会自行关闭。哦,很抱歉缩进,只是手动编写了伪代码:S.+1以获取帮助您无法重新绑定同一套接字。您必须关闭它并创建一个新端口,或者停止对其调用accept,稍后再继续。问题是我无法创建一个新端口,因为我有许多客户端正在转发到此特定端口。现在的解决方案是停止整个OSGi框架,这对我的应用程序来说不是很好。应该有任何类型的方法来控制匿名线程在捆绑包中的行为,但是我找不到合适的解决方案。我不熟悉这个框架。在开始/停止事件时,是否有来自it的任何挂钩/回调?我认为您需要重写一些函数,在这些函数中您可以创建/关闭套接字。注意,这些可能在不同的线程上。你是对的,套接字不会自动关闭。你认为OSGi会为你免费处理这件事吗??在bundle的start方法中创建的任何内容都必须在stop方法中清除。这包括您打开的任何套接字、启动的任何线程等。这是您作为捆绑包作者的责任,而不是其他任何人的责任。如果你需要重新构造你的代码使之成为可能,那么就这样吧。谢谢你的回答。我在使用您的方法时面临的唯一问题是,我已经过多地重载了activator,因此我不想再在其中编写代码。启动和停止方法应简单,以避免捆绑激活过程中的任何延迟。无论如何,你给了我一个未来部署的好主意+1在这种情况下,您必须以某种方式将启动和停止逻辑与函数和类分开。但是,如果创建新类,它们还必须具有停止/关闭功能。无论如何,唯一的解决方案是当捆绑包停止时,您能够停止服务器套接字。感谢您的回答。我在使用您的方法时面临的唯一问题是,我已经过多地重载了activator,因此我不想再在其中编写代码。启动和停止方法应简单,以避免捆绑激活过程中的任何延迟。无论如何,你给了我一个未来部署的好主意+1在这种情况下,您必须以某种方式将启动和停止逻辑与函数和类分开。但是,如果创建新类,它们还必须具有停止/关闭功能。无论如何,唯一的解决方案是在捆绑包停止时停止服务器套接字。关于只接收一个客户端的问题是因为伪代码,我的真实代码接受多个连接。彼得,非常感谢你的回答。不仅是为了规范,也是为了建议。收到Peter Kriens的答复真的很荣幸。谢谢只接收一个客户端的问题是因为伪代码,我的真实代码接受多个连接。彼得,非常感谢你的回答。 不仅是为了规范,也是为了建议。收到Peter Kriens的答复真的很荣幸。谢谢