在Eclipse外工作时,Java TCP Client无响应

时间:2015-12-06 03:44:15

标签: java eclipse sockets networking tcp

当连接到本地TCP服务器时,我无法让我的客户端Java应用程序响应。服务器显示客户端已连接,但客户端未从服务器接收更新并保持静态。但是,当我在Eclipse中运行时,它工作得很好。但是在将每个导出到可执行jar文件后,我没有运气。我环顾四周,并认为它可能是我的Windows防火墙,我已禁用,但它仍然无法正常工作。

TCP服务器在本地运行,客户端只是通过服务器机器拥有的任何本地IP地址进行连接。即使在同一台机器上(但在Eclipse之外)测试客户端和服务器,客户端仍然没有响应,但服务器显示它已连接客户端。我只是不知道eclipse正在做什么来使应用程序运行不同于外部工作。任何建议都非常感谢!谢谢。

通信的设置方式是我们有一个主JSON对象,它包含客户端接收的命令。根据命令,客户端会以某种方式做出反应。在服务器上,每个客户端都是独立的线程。当客户端首次连接时,服务器会添加它们并创建一个新的ServerClient来连接来回通信。加入后,服务器应将所有连接的客户端回显给加入的客户端,并且它将显示在客户端GUI中。涉及的内容更多,但这是基本的客户端 - 服务器通信链接。

服务器:

/**
 * Constructs a new Server with a link to the ServerApp.
 * @param app - Target ServerApp
 */
public Server(ServerApp app) {
    this.app = app;
    clients = new HashMap<>();
    serverDir = new ServerDirector(this);
}

/**
 * Main server loop. Waits and listens for new clients.
 */
public void run() {
    while (running) {
        try {
            // wait and accept new clients
            app.log("Waiting for client...");
            addClient(serverSocket.accept());
        } catch (SocketException e) {   // terminate if socket is closed!
            running = false;
        } catch (EOFException e) {
            running = false;
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

/**
 * Opens server socket on defined PORT.
 * @throws IOException
 */
public void open() throws IOException {
    serverSocket = new ServerSocket(portNo);
}

/**
 * Adds a client to the clients map.
 * @param socket - Socket to allow server client to connect
 * @throws IOException
 */
public void addClient(Socket socket) throws IOException {
    if (clients.size() < MAX_CLIENTS) {
        int ID = serverDir.getPlayers().size();
        System.out.println("Socket: " + socket);
        ServerClient sc = new ServerClient(ID, socket, this);
        sc.open();
        sc.start();
        sc.echoID(); // echo ID to main client thread
        NewJSONObject k = new NewJSONObject(ID, Keys.Commands.CONNECT); // send connection status!
        k.put(Keys.CONNECT_STATUS, 1);  // connection is good!
        sc.getIOHandler().send(k);
        clients.put(ID, sc);
    } else {
        System.out.println("Client limit reached. Client connection refused!");
    }
}

客户端:

    /**
 * Constructs a client with link to main app, and specified ID and socket.
 * @param app - ClientApp
 * @param ID - ID to assign
 * @param socket - Socket to connect to
 */
public Client(ClientApp app, int ID, Socket socket) {
    this.app = app;
    this.ID = ID;
    this.socket = socket;
}

/**
 * Starts this thread.
 */
public void start() {
    running = true;
    super.start();
}

/**
 * Main thread loop. Listens to input received on InputStream.
 */
public void run() {
    while (running) {
        try {
            ioHandler.receive((JSONObject)streamIn.readObject());
        } catch (EOFException | SocketException e) {
            running = false;
            try {
                terminate();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

/**
 * Attempts to connect to the specified socket.
 * @param socket - Socket to connect to.
 * @throws IOException
 */
public void connect(Socket socket) throws IOException {
    this.socket = socket;
    open();
    connected = true;
}

/**
 * Opens I/O streams.
 * @throws IOException
 */
public void open() throws IOException {
    streamOut = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
    streamOut.flush();
    streamIn = new ObjectInputStream(new BufferedInputStream(socket.getInputStream()));
}
  • ServerClient扩展了Client,因为它们共享相同的功能。虽然ServerClient有一个指向服务器的链接,但客户端是通过服务器通过其他客户端进行通信的方式。

因此,一旦客户端连接,我就有一个服务器GUI,其中包含所有连接客户端的列表。然后,ServerDirector(处理数据包)发送“addPlayer”命令,该客户端解释并将JSON数据包中指定的名称添加到GUI。该名称出现在客户端上,然后一旦有2个以上的玩家加入,就会发送更多命令以在各种状态之间进行转换。一切都在Eclipse中工作正常,但是一旦应用程序是外部jar,客户端保持静态,即使服务器显示客户端确实已连接。在Eclipse外部运行时,客户端不会收到任何数据包更新。

1 个答案:

答案 0 :(得分:1)

我想出了这个问题。从eclipse导出时,应用程序使用的所有资源文件(如播放器精灵)都没有在正确的目录中,导致多个FileNotFoundExceptions和NullPointerExceptions并导致客户端无法运行,因为其他组件依赖于res文件。只需将res文件夹添加到jar就可以解决问题了!