Java - 程序在eclipse中完美运行,但在导出到runnable jar时似乎没有完成预期的任务

时间:2014-07-04 08:20:58

标签: java eclipse sockets

我不确定此问题是否已经发布过,但这看起来非常具体,我不知道出了什么问题。

基本上我想要实现的是, - 有一台服务器' ServerSocket等待接收连接的程序的位 - 用户将运行客户端并连接到该套接字。 - 然后用户可以将数据包发送到服务器'其他一些东西。

需要注意的是,我正在检查套接字是否为空,如果是,则允许连接。否则它将被忽略,因为只需要一个用户连接一次。但是,当用户断开连接时,用户可以重新连接到同一个套接字并继续。

这是接收服务器'位。

private void shutDownSocket() {
    try {
        socket.close();
        socket = null;
    } catch (IOException e) {
        e.printStackTrace();
    }

}

class Getting extends Thread {
    public void run() {
        boolean running = true;
        try {
            in = new ObjectInputStream(socket.getInputStream());
            System.out.println("connected");

            while (running) {
                int retVal = interpret((Packet) in.readObject());
                if (retVal == 0) {
                    running = false;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("connection lost");
            running = false;
            shutDownSocket();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Cycle extends Thread {
    public void run() {
        try {
            ServerSocket server = new ServerSocket(2323);

            while (true) {
                if (socket == null) {
                    socket = server.accept();
                    new Getting().start();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

因此,当我在eclipse中运行我的所有代码时,一切都运行得很好,它可以完成我想要它做的所有事情。但是当我导出客户端和服务器部件并在不同的计算机上运行它时,我可以第一次连接,一切都很完美。但当我关闭我的客户。 (它发送一个数据包,告诉服务器使socket = null)并重新连接,它再次工作了。

我感谢你们给予的任何帮助。感谢。

2 个答案:

答案 0 :(得分:1)

您需要某种形式的同步。

基本情况:

final Object sync = new Object();

private void shutDownSocket() {
    try {
        synchronized(sync){
          socket.close();
          socket = null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

}

在接受

class Cycle extends Thread {
    public void run() {
        try {
            ServerSocket server = new ServerSocket(2323);

            while (true) {

                synchronized(sync){
                  if (socket == null) {
                    socket = server.accept();
                    new Getting().start();
                  }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

编辑:

class Getting extends Thread {
    public void run() {
        boolean running = true;
        try {
            in = new ObjectInputStream(socket.getInputStream());
            System.out.println("connected");

            while (running) {
                int retVal = interpret((Packet) in.readObject());
                if (retVal == 0) {
                    running = false;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("connection lost");
            running = false;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally{

            shutDownSocket();
        }
    }
}

在IDE上运行时,运行的线程太多,在ServerSocket收到传入请求的通知之前,Getting线程可能会将套接字设置为null

答案 1 :(得分:1)

每次接受连接时产生额外线程的唯一原因是服务器可以一次接受多个连接。

如果您只想接受一个连接,那么只需在您接受的同一个线程上处理该连接:

public class Server implements Runnable {
    @Override
    public void run() {
        try {
            ServerSocket server = new ServerSocket(2323);
            try {
                while (true)
                    processConnection(server.accept());
            } finally {
                server.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void processConnection(Socket socket) throws IOException {
        System.out.println("got connection");
        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        try {
            while (interpret((Packet) in.readObject()) != 0);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    ...
}

您不需要线程,同步或类似的东西。