当连接到本地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()));
}
因此,一旦客户端连接,我就有一个服务器GUI,其中包含所有连接客户端的列表。然后,ServerDirector(处理数据包)发送“addPlayer”命令,该客户端解释并将JSON数据包中指定的名称添加到GUI。该名称出现在客户端上,然后一旦有2个以上的玩家加入,就会发送更多命令以在各种状态之间进行转换。一切都在Eclipse中工作正常,但是一旦应用程序是外部jar,客户端保持静态,即使服务器显示客户端确实已连接。在Eclipse外部运行时,客户端不会收到任何数据包更新。
答案 0 :(得分:1)
我想出了这个问题。从eclipse导出时,应用程序使用的所有资源文件(如播放器精灵)都没有在正确的目录中,导致多个FileNotFoundExceptions和NullPointerExceptions并导致客户端无法运行,因为其他组件依赖于res文件。只需将res文件夹添加到jar就可以解决问题了!