【问题标题】:Java Socket's app randomly stoppingJava Socket 的应用程序随机停止
【发布时间】:2009-11-04 04:13:06
【问题描述】:

服务器

public void run () {

 Socket serversocket = new ServerSocket(port);
 while(true) {
   new Thread(new ServerThread(serverSocket.accept())).start();
 }
}
//serverSocket.close(); etc

服务器线程

public void run() {
 BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

 String input;

 while(true) {
   input = in.readLine();
   new Thread(new RequestThread(clientSocket, input)).start();
 }
}
//close sockets etc in.close() clientSocket.close();

请求线程

public void run() { 
 //input was passed from constructor
 String output = new SomeProtocol(input);

 if(output == null)
  break;
 //true for auto flush
 PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
 out.println(output);
}//closing out seems to also close the socket, so opted to not to close it, maybe this is the one giving me trouble?

监控

public class ServerMonitor implements Runnable{
    private ServerThread server;
    private LoggingClass log = LoggingClass .getInstance();
    private int heartbeat = 0;

    public ServerMonitor(ServerThread server) {
        this.server = server;
    }

    public boolean checkFile() {
        File file = new File("cmd//in//shutdown.txt");
        return file.exists();
    }

    public void run() {

        log.logToFile("Server monitor running");

        while (true) {
            incHeartbeat();
            if (checkFile()) {
                log.logToFile("Shutting down server");
                break;
            }
            writeStatus();
            this.delay(5000);
        }

        log.logToFile("Server monitor stopped");
    }

    public void delay(long delay) {
        try {
            wait(delay);
        } catch (InterruptedException e) {
            log.logToFile("Monitor sleep error");
            e.printStackTrace();
        }
    }

    public void writeStatus() {
        try {
            BufferedWriter out = new BufferedWriter(new FileWriter(
                    "sys//status//status.txt"));
            out.write("Start date:" + log.getStartDate());
            out.newLine();
            out.write("Current date:" + log.getTimestamp("yyyy-MMM-dd k:mm:ss"));
            out.newLine();
            out.write("Heartbeat:" + getHeartbeat());
            out.newLine();
            out.write("Cimd in:" + log.getCimdIn());
            out.newLine();
            out.write("Cimd out:" + log.getCimdOut());
            out.newLine();
            out.write("Keep alive:" + log.getCimdKeepAlive());
            out.newLine();
            out.write("HTTP in:" + log.getNumHTTPIn());
            out.newLine();
            out.write("HTTP out:" + log.getNumHTTPOut());
            out.newLine();
            out.close();

        } catch (Exception e) {
            log.logToFile("Write status error");
            e.printStackTrace();
        }
    }

    public int getHeartbeat() {
        return heartbeat;
    }

    public synchronized void incHeartbeat() {
        heartbeat++;
    }
}

这是我的应用程序的粗略骨架。我遇到了麻烦,因为有时它只是停止而没有任何错误。我怀疑这可能是因为插座,但我不太确定,所以你们中的任何人有什么想法吗?谢谢。


添加了我的监控服务器线程的类

>How do I know that it doesn't work

心跳不再增加

【问题讨论】:

  • 我不知道问题出在哪里,但我建议您添加一些日志记录以帮助您查看应用程序在关闭时正在执行的操作。
  • 关机需要多长时间?
  • 随机的,有时会持续几天,有时甚至不会持续一个小时
  • 至少不是即时的。您还可以将一些分析器附加到您的应用程序并查看发生了什么。分析器可能会告诉您哪些资源导致了可能的死锁或堆栈溢出。看看 Java 6 附带的 jConsole(我认为是从 Java 5 开始)
  • 服务器上的java是1.4.3(他们不会更新ffs)

标签: java multithreading sockets


【解决方案1】:

您可能内存/线程不足

你是否碰巧有一些像这样的高级异常处理:

public static void main( String ... args ) {
    try {
        // lots of code ... 
    } catch( Exception e ) {}
}

如果是这样,您至少必须记录您忽略的错误。

这正是我想到的,因为我手头没有你的源代码。

【讨论】:

  • 是的,我有。但它什么也没显示,只是停止了。
  • :-) 如果您这样做,请暂时将其删除,然后看看发生了什么。或者至少让它catch( Exception e ) { e.printStackTrace(); } 捕获所有异常不是一个好主意。你应该抓住你期望发生的事情。或者至少记录发生了什么。
  • 它没有显示任何内容,因为您忽略了异常。
  • 已经设置为 e.printstacktrace。是的,我也在记录它,但就像我说的它只是停止了,它仍然列在进程处理程序中,但是我的监视服务器的线程声明它停止了
  • 当您遇到系统错误(例如 OutOfMemoryError )时,您不会在日志中获得太多信息,因为您不应该处理它们。如果没有看到更多代码,就不可能确定发生了什么。我的建议是完全删除 try/catch 并看看会发生什么。如果遇到异常,您可以添加特定的 catch 部分。这样做,我想你就能弄清楚发生了什么
【解决方案2】:

您能否更好地定义“停止工作”?它是否停止接受连接?它会崩溃吗?它是否在处理过程中停止做某事?等等?

有一点猜测是,当套接字关闭时,我不确定读者会发生什么。我期望发生的是,尝试使用关闭的套接字调用 read 行会导致异常,这将停止该线程,和/或可能终止整个应用程序。这会产生堆栈跟踪和其他问题。

基本上,除了 Oscar 所说的 main 中的异常日志;你会想要登录任何 run() 方法。 main 中的 try/catch 只会捕获主线程抛出的异常;不是那些在其他线程中抛出的。

【讨论】:

    【解决方案3】:

    很难从您发布的伪代码中看出,但如果应用程序挂起(而不是彻底崩溃),我最好的猜测是 ServerThread 中的 in.readLine() 正在阻塞。如果应用程序刚刚关闭,我会查看套接字闭包,并可能在 BufferedReader 中检查 isReady()。

    一般性评论:您在这里生成的线程可能比您需要的多。看起来从客户端套接字读取和写入它是串行发生的。如果是这种情况,ServerThread Runnable(我假设它是 Runnable,因为您将其传递给 Thread 的构造函数)不一定需要生成 RequestThread。

    public class ServerRunnable implements Runnable {
        ...
    
        public void run() {
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    
             String input;
    
             while(true)
             {
               input = in.readLine();
               if(input == null)
               {
                   //this means the underlying socket closed
                   //log something here or return or whatever
               }
    
               String output = new SomeProtocol(input);
    
               if(output == null)
                break;
               //true for auto flush
               PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
               out.println(output);
             }
        }
        ...
    }
    

    【讨论】:

    • 这就是我在以前的版本中所做的,它仍然停止了。
    • 哦,把服务器想象成一个调度程序,每个字符串都做自己的事情,这就是为什么我为每个请求创建一个新线程的原因。我应该将它恢复到以前的版本吗?
    • 附录:我怀疑它卡在 in.readLine() 中,因为监视器线程的心跳随之停止(不应该发生,因为它完全是一个不同的线程)。套接字关闭:我正确地关闭了它我什至在线程停止时记录了我的记录器,但是当它挂起时,我没有看到它实际上记录了它刚刚停止的任何内容。 (把它想象成有人在运行时杀死了你的程序)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2020-06-22
    • 1970-01-01
    • 2022-12-24
    • 2019-01-06
    • 2012-01-13
    • 2015-01-25
    相关资源
    最近更新 更多