Java 使用网络服务器部署OSGI捆绑包时的无限循环

Java 使用网络服务器部署OSGI捆绑包时的无限循环,java,networking,maven,network-programming,glassfish,Java,Networking,Maven,Network Programming,Glassfish,我正在尝试用使用网络套接字的网络服务器实现OSGI捆绑包。 这是完整的源代码: 这是激活剂: package org.DX_57.osgi.CB_27.impl; import java.util.Properties; import org.DX_57.osgi.CB_27.api.CBridge; import org.DX_57.osgi.CB_27.impl.EchoServer; import org.osgi.framework.BundleActivator; import or

我正在尝试用使用网络套接字的网络服务器实现OSGI捆绑包。 这是完整的源代码:

这是激活剂:

package org.DX_57.osgi.CB_27.impl;

import java.util.Properties;
import org.DX_57.osgi.CB_27.api.CBridge;
import org.DX_57.osgi.CB_27.impl.EchoServer;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

public class CBridgeApp implements BundleActivator {

    public void start(BundleContext bc) throws Exception {
        ServiceRegistration registerService = bc.registerService(CBridge.class.getName(), new CBridgeImpl(), new Properties());
        EchoServer();
    }

    public void stop(BundleContext bc) throws Exception {
        boolean ungetService = bc.ungetService(bc.getServiceReference(CBridge.class.getName()));
    }

    private void EchoServer() {
        EchoServer method = new EchoServer();
    }
}
这是Java网络服务器的源代码:

package org.DX_57.osgi.CB_27.impl;

import java.net.*;
import java.io.*;

public class EchoServer
{        
    ServerSocket m_ServerSocket;


    public EchoServer() 
    {
        try
        {
            // Create the server socket.
            m_ServerSocket = new ServerSocket(12111);
        }
        catch(IOException ioe)
        {
            System.out.println("Could not create server socket at 12111. Quitting.");
            System.exit(-1);
        }

        System.out.println("Listening for clients on 12111...");

        // Successfully created Server Socket. Now wait for connections.
        int id = 0;
        while(true)
        {                        
            try
            {
                // Accept incoming connections.
                Socket clientSocket = m_ServerSocket.accept();

                // accept() will block until a client connects to the server.
                // If execution reaches this point, then it means that a client
                // socket has been accepted.

                // For each client, we will start a service thread to
                // service the client requests. This is to demonstrate a
                // multithreaded server, although not required for such a
                // trivial application. Starting a thread also lets our
                // EchoServer accept multiple connections simultaneously.

                // Start a service thread

                ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
                cliThread.start();
            }
            catch(IOException ioe)
            {
                System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
                ioe.printStackTrace();
            }
        }
    }

    public static void main (String[] args)
    {
        new EchoServer();    
    }


    class ClientServiceThread extends Thread
    {
        Socket m_clientSocket;        
        int m_clientID = -1;
        boolean m_bRunThread = true;

        ClientServiceThread(Socket s, int clientID)
        {
            m_clientSocket = s;
            m_clientID = clientID;
        }

        public void run()
        {            
            // Obtain the input stream and the output stream for the socket
            // A good practice is to encapsulate them with a BufferedReader
            // and a PrintWriter as shown below.
            BufferedReader in = null; 
            PrintWriter out = null;

            // Print out details of this connection
            System.out.println("Accepted Client : ID - " + m_clientID + " : Address - " + 
                             m_clientSocket.getInetAddress().getHostName());

            try
            {                                
                in = new BufferedReader(new InputStreamReader(m_clientSocket.getInputStream()));
                out = new PrintWriter(new OutputStreamWriter(m_clientSocket.getOutputStream()));

                // At this point, we can read for input and reply with appropriate output.

                // Run in a loop until m_bRunThread is set to false
                while(m_bRunThread)
                {                    
                    // read incoming stream
                    String clientCommand = in.readLine();

                    System.out.println("Client Says :" + clientCommand);


                    if(clientCommand.equalsIgnoreCase("quit"))
                    {
                        // Special command. Quit this thread
                        m_bRunThread = false;   
                        System.out.print("Stopping client thread for client : " + m_clientID);
                    }
                    else
                    {
                        // Echo it back to the client.
                        out.println(clientCommand);
                        out.flush();
                    }
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                // Clean up
                try
                {                    
                    in.close();
                    out.close();
                    m_clientSocket.close();
                    System.out.println("...Stopped");
                }
                catch(IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
        }
    }
} 
当我尝试在Glassfish服务器上部署捆绑包时,应用程序服务器挂起,但我可以使用java客户端连接到java网络服务器。似乎有一个无限循环。我需要帮助来修复代码


最好的祝愿

您的bundle activator start方法永远不会返回,因为您正在使用无限循环调用服务的构造函数。一个好的做法是尽可能快地从束激活器返回

下面是一个如何重写代码的想法:

public class EchoServer {
    private volatile boolean started;
    public void start() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                started = true;

                try {
                    m_ServerSocket = new ServerSocket(12111);
                } catch(IOException ioe) {
                    System.out.println("Could not create server socket at 12111. Quitting.");
                    System.exit(-1);
                }
                System.out.println("Listening for clients on 12111...");

                // Successfully created Server Socket. Now wait for connections.
                int id = 0;

                while (started) {
                    try {

                        Socket clientSocket = m_ServerSocket.accept();
                        ClientServiceThread cliThread = new ClientServiceThread(clientSocket, id++);
                        cliThread.start();    
                    } catch(IOException ioe) {
                        System.out.println("Exception encountered on accept. Ignoring. Stack Trace :");
                        ioe.printStackTrace();
                    }
                }
            }
        }).start();
    }
    public void stop() {
        started = false;
    }
}
活化剂

public class CBridgeApp implements BundleActivator {
    private EchoServer method;
    public void start(BundleContext bc) throws Exception {
        ...

        method = new EchoServer();
        method.start();
    }
    public void stop(BundleContext bc) throws Exception {
        ...

        method.stop();
    }
}

回答得很好。我不理解代码的某些部分。您是否可以添加缺少的(…)部分?谢谢。在bundle activator中,最好由您决定应该添加哪些缺少的部件,因为我不明白您为什么需要在那里获取并取消设置CBridge的服务引用。该服务已更新,但我没有检查是否可以编译。好消息是我可以编译代码,并且可以成功地将其上传到Glassfish上。java网络客户端可以成功地与服务器通信。坏消息是,当我取消部署包并再次部署它时,Glassfish服务器崩溃。这是错误日志:无法创建套接字。可能旧的套接字连接没有清理?您必须关闭ServerSocket。这可以在EchoServer.stop()方法中完成。是的,我这样修改了代码:现在它可以工作了,Glassfish没有崩溃。剩下的一件事是:当我取消部署包时,客户端可以再次连接一次。这意味着我认为插座没有关闭。然后我尝试再次连接,连接冻结。我想插座没有关上或清洁。我需要在运行stop()方法时关闭套接字。我需要修改代码的某些部分,并使某些部分像IN和OUT一样可见。我怎么能做到?我尝试过,但在stop()方法中看不到它们。