我正在用LibGDX开发一个Android游戏,并且正在用Java创建该游戏的服务器。我的游戏通过套接字在服务器的不同端口上创建了两个连接。例如在端口6000上创建第一连接后,它将在端口6001上创建第二连接。第一连接用于客户端到服务器之间的通信,第二连接用于服务器到客户端之间的通信。 一切正常,直到我第二次失去互联网连接才能重新连接逻辑。
这是它的工作方式: 在服务器上,我有一个“接收”,它是一个接受所有传入连接的类,如果该连接(IP)尚未与可用客户端一起保存在列表中,则该接收器将创建新线程(工作器)。创建新工作线程时,它将获得一个Socket作为参数,并创建输入和输出流,并开始读取传入消息。 客户端创建第一个连接后,它将创建一个新线程并在其上启动新连接。然后,接收获得第二个连接,检测到该IP已在列表中,并将此Socket设置为现有工作器作为第二个连接。
如果客户端失去连接(在第二个通道上我得到ServerSocketException
),然后客户端关闭所有输入和输出流以及两个套接字。然后等待几秒钟,然后尝试像开始时一样初始化服务器通信。如果它不起作用,它将再次清理所有内容,等待并再次尝试...
在服务器端,当接收到与第一个连接相同的IP和端口时,它会搜索正确的工作线程,并使用新的套接字作为参数调用重新连接。该工作人员像客户端一样进行清理。它清除所有输入,输出流并关闭两个套接字。然后,它像创建时一样在开始时初始化第一个连接。
当我失去互联网连接并再次重新连接时,这将首次起作用。但是当我再次这样做时,会发生一些奇怪的事情。客户端尝试在第一个通道上重新连接,并说连接成功。但是服务器接收没有任何连接! 然后,客户端启动第二个连接,并在接收到该连接。所以我不明白,为什么我已经有一次重新连接的第一次连接没有到达服务器的接收端。 我希望有人可以帮助我
这是重要的客户代码。我还应该添加一些服务器端代码吗?
private void initializeServerCommunication() {
if (clientSocket == null) {
SocketHints socketHints = new SocketHints();
socketHints.connectTimeout = 4000;
socketHints.keepAlive = true;
clientSocket = Gdx.net.newClientSocket(Net.Protocol.TCP, HOST, 6078, socketHints);
outputStream = clientSocket.getOutputStream();
inputStream = clientSocket.getInputStream();
timeoutService = Executors.newSingleThreadScheduledExecutor();
timeoutFuture = timeoutService.scheduleAtFixedRate(keepAliveRunnable, KEEP_ALIVE_TIMEOUT, KEEP_ALIVE_TIMEOUT, TimeUnit.SECONDS);
}
if (listenerSocket == null) {
// create second thread to listen for incoming messages from server
new Thread(new Runnable() {
@Override
public void run() {
try {
SocketHints socketHints = new SocketHints();
socketHints.connectTimeout = 4000;
socketHints.keepAlive = true;
listenerSocket = Gdx.net.newClientSocket(Net.Protocol.TCP, HOST, 6079, socketHints);
serverClientOutputStream = listenerSocket.getOutputStream();
serverClientInputStream = listenerSocket.getInputStream();
int result = 0;
while (result != -1) {
try {
result = serverClientInputStream.read();
} catch (Exception e) {
Gdx.app.log(TAG, "Server - Client Connection lost. Try to reconnect");
reconnect(); // start reconnection
Thread.currentThread().interrupt();
}
if (result != -1) {
switch (result) {
...
}
}
}
}
}
}).start();
}
}
private void reconnect() {
cleanUp();
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
reConnectFuture = scheduledExecutorService.scheduleAtFixedRate(reConnectorRunnable, RECONNECT_INTERVAL, RECONNECT_INTERVAL, TimeUnit.SECONDS);
}
private Runnable reConnectorRunnable = new Runnable() {
@Override
public void run() {
try {
initializeServerCommunication();
stopReconnectionService();
if (errorHandlingListener != null) {
errorHandlingListener.reconnected();
} else {
Gdx.app.error(TAG, "Reconnected but could not inform the app about it.");
}
} catch (GdxRuntimeException r) {
reconnectAttemptsLeft--;
cleanUp();
if (reconnectAttemptsLeft <= 0) {
stopReconnectionService();
}
} catch (Exception e) {
reconnectAttemptsLeft--;
cleanUp();
if (reconnectAttemptsLeft <= 0) {
stopReconnectionService();
}
}
}
};
private void stopReconnectionService() {
reconnectAttemptsLeft = MAX_RECONNECT_ATTEMPTS;
reConnectFuture.cancel(true);
}
private void cleanUp() {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException i) {
Gdx.app.log(TAG, "Could not close client - server input stream");
}
inputStream = null;
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
Gdx.app.log(TAG, "Could not close client - server output stream");
}
outputStream = null;
}
if (serverClientInputStream != null) {
try {
serverClientInputStream.close();
} catch (IOException e) {
Gdx.app.log(TAG, "Could not close server - client input stream");
}
serverClientInputStream = null;
}
if (serverClientOutputStream != null) {
try {
serverClientOutputStream.close();
} catch (IOException e) {
Gdx.app.log(TAG, "Could not close server - client output stream");
}
serverClientOutputStream = null;
}
if (clientSocket != null) {
clientSocket.dispose();
}
clientSocket = null;
if (listenerSocket != null) {
listenerSocket.dispose();
}
listenerSocket = null;
}