Digital Ocean java 服务器不断崩溃:java.net.SocketException:连接重置
Digital Ocean java server keeps crashing: java.net.SocketException: Connection reset
我正在使用 Digital Ocean 服务器来促进我的 PC 游戏中的在线多人游戏。服务器是用 Java 编写的一个小应用程序。问题是服务器偶尔会关闭并在大约 15 分钟后自动重新启动。我已经升级了几次服务器,但似乎没有任何区别,最后我使用了 CPU 优化的 Droplet,具有 4 GB 内存 2 vCPUs 和 20 GB 磁盘。我不完全确定,但当大约有 15 个人在线时服务器似乎宕机了,但有时在线人数相同(或更多)并且没有发生崩溃。当大多数人在线时,它每天大约崩溃 1-2 次。
图表:
-1 分钟后服务器崩溃(晚上 7:29):https://imgur.com/a/Asit3O6
-服务器停机 12 分钟(晚上 7:41):https://imgur.com/a/ulIgTau
-服务器重新上线(晚上 7:50):https://imgur.com/a/gMOn4Jf
-服务器重新联机 28 分钟(晚上 8:18):https://imgur.com/a/lA8dufN
控制台:
-服务器崩溃后(晚上 7:39):https://imgur.com/a/h7r701H
它显示:
java.net.SocketException: Connection reset
-服务器重新上线后(晚上7:50):https://imgur.com/a/l85FYFw
我唯一认识的是 ClientThread.java 文件,它是构成服务器的 3 个 java 文件之一。
我还必须说,我对 Java 的体验非常基础,java 服务器文件是由其他人制作的(谁不可用),但我理解其中的大部分内容并自己做了一些小的调整。
为什么这个服务器偶尔会崩溃?
这是 ClientThread.java 文件:
import java.util.Iterator;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.Socket;
//
// Decompiled by Procyon v0.5.30
//
public class ClientThread extends Thread
{
Socket clientSocket_;
String clientIp_;
String serverIp_;
ServerInformation server_;
PrintWriter out_;
BufferedReader in_;
boolean prepareTermination_;
boolean terminated_;
private static final Pattern numberPattern;
static {
numberPattern = Pattern.compile("\d+");
}
public ClientThread(final Socket sock) {
this.clientSocket_ = sock;
this.clientIp_ = this.clientSocket_.getRemoteSocketAddress().toString();
this.serverIp_ = null;
this.server_ = null;
this.prepareTermination_ = false;
this.terminated_ = false;
}
@Override
public void run() {
try {
//this.logDebugMessage(2, "Client socket accepted, ip: " + this.clientIp_);
this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);
this.in_ = new BufferedReader(new InputStreamReader(this.clientSocket_.getInputStream()));
long lastActionTime = System.currentTimeMillis();
while (true) {
if (this.in_.ready() || System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
if (System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
//this.logDebugMessage(3, "Thread was killed due to prolonged inactivity (" + Main.threadTimeout_ + " seconds)");
this.terminateThread();
return;
}
lastActionTime = System.currentTimeMillis();
final String inputLine = this.in_.readLine().trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()) {
final int val = Integer.parseInt(inputLine);
switch (val) {
case 111: { //send to client fast b
final StringBuilder msg = new StringBuilder();
msg.append(String.valueOf(this.in_.readLine().trim()));
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
break;
}
case 110: { //send to ip fast
final String ip = this.in_.readLine().trim();
final ClientThread target = this.server_.ipToClientThread_.getOrDefault(ip, null);
if (target != null) {
target.out_.print(this.in_.readLine().trim());
target.out_.flush();
break;
}
}
case 109: { //send to server fast
this.server_.out_.print(this.in_.readLine().trim());
this.server_.out_.flush();
break;
}
case 108: { //send to all fast
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(this.in_.readLine().trim());
thread2.out_.flush();
}
break;
}
case 107: { //send to others fast
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(this.in_.readLine().trim());
thread2.out_.flush();
}
}
break;
}
case 106: {
this.server_.description_ = this.in_.readLine().trim(); //class
break;
}
case 105: {
this.out_.print("*" + 26 + "|" + this.server_.servervar3_ + "|" + this.server_.servervar4_ + "|" + this.server_.servervar5_ + "~" + "|");
this.out_.flush();
break;
}
case 104: {
this.server_.servervar5_ = this.in_.readLine().trim(); //status
break;
}
case 103: {
this.server_.servervar3_ = this.in_.readLine().trim(); //current lap
break;
}
case 102: {
this.server_.servervar3_ = this.in_.readLine().trim(); //current lap
this.server_.servervar4_ = this.in_.readLine().trim(); //total laps
this.server_.servervar5_ = this.in_.readLine().trim(); //status
break;
}
case 101: { //admin quit server
final String ipServer = this.in_.readLine().trim();
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
this.server_ = info;
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
break;
}
case 100: {
if (System.currentTimeMillis() - this.server_.servervar2_ >= 1000 * 20) { //clients check if server is still online
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
final String ipServer = this.server_.ip_;
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
}
break;
}
case 99: {
this.server_.servervar2_ = System.currentTimeMillis(); //send server last update
break;
}
case 98: {
final String ipServer = this.in_.readLine().trim();
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
this.serverIp_ = null;
for (final ClientThread thread : this.server_.ipToClientThread_.values()) {
thread.prepareTermination_ = true;
}
this.terminateThread();
return;
}
case 96: {
final String ipServer = this.in_.readLine().trim();
final String ipClient = this.in_.readLine().trim();
//this.logDebugMessage(1, "A client wishes to connect to a server, client: " + ipClient + ", server: " + ipServer);
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
if (info == null) {
System.out.println("Connection to the server failed, no such server in the server list");
out_.print("*" + 1 + "|" + 1 + "~" + "|");
out_.flush();
break;
}
this.server_ = info;
this.server_.ipToClientThread_.put(ipClient, this);
this.server_.numplayers_ += 1;
//this.logDebugMessage(1, "Connection success");
out_.print("*" + 1 + "|" + 2 + "~" + "|");
out_.flush();
break;
}
case 95: {
final String ipClient = this.in_.readLine().trim();
this.server_.ipToClientThread_.remove(this);
this.server_.numplayers_ -= 1;
//this.logDebugMessage(1, String.valueOf(ipClient) + " disconnected from the server at " + this.server_.ip_);
this.terminateThread();
return;
}
case 94: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int i = 0; i < parseCount; ++i) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
this.server_.out_.print(msg.toString());
this.server_.out_.flush();
//this.logDebugMessage(5, "Packet for server: '" + msg.toString() + "'");
break;
}
case 93: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final String ip = this.in_.readLine().trim();
final StringBuilder msg = new StringBuilder();
for (int i = 0; i < parseCount - 1; ++i) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
final ClientThread target = this.server_.ipToClientThread_.getOrDefault(ip, null);
if (target != null) {
target.out_.print(msg.toString());
target.out_.flush();
//this.logDebugMessage(5, "Packet for " + ip + ": '" + msg.toString() + "'");
break;
}
//this.logDebugMessage(1, "Packet for " + ip + " failed to send (recipient not found)");
break;
}
case 92: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(msg);
thread2.out_.flush();
}
//this.logDebugMessage(5, "Packet for all: '" + msg.toString() + "'");
break;
}
case 91: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
//this.logDebugMessage(5, "Packet for others: '" + msg.toString() + "'");
break;
}
case 90: {
//this.logDebugMessage(2, "A socket has requested the advanced server list, server list size: " + Main.servers_.size());
if (Main.servers_.size()==0) {
this.out_.print("*" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "~" + "|");
} else {
for (final ServerInformation info2 : Main.servers_.values()) {
this.out_.print("*" + String.valueOf(info2.name_) + "|" + info2.ip_ + "|" + info2.description_ + "|" + info2.servervar1_ + "|" + info2.servervar2_ + "|" + info2.servervar3_ + "|" + info2.servervar4_ + "|" + info2.servervar5_ + "|" + info2.numplayers_ + "|" + info2.ipToClientThread_.size() + "|" + info2.servervar6_ + "|" + info2.servervar7_ + "~" + "|");
if (System.currentTimeMillis() - info2.servervar2_ >= 1000 * 20) {
final String ipServer = info2.ip_;
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
this.server_ = info;
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
}
}
}
this.out_.flush();
break;
}
case 89: {
final String ipServer = this.in_.readLine().trim();
final String name = this.in_.readLine().trim(); //Server name
final String description = this.in_.readLine().trim(); //class
final String servervar1 = this.in_.readLine().trim(); //max players
final String servervar3 = this.in_.readLine().trim(); //current lap
final String servervar4 = this.in_.readLine().trim(); //total laps
final String servervar5 = this.in_.readLine().trim(); //status
final String servervar6 = this.in_.readLine().trim(); //Password
final String servervar7 = this.in_.readLine().trim(); //Online version
//this.logDebugMessage(1, "A game server has been registered, ip: " + ipServer + ", name: " + name + ", description: " + description + ", servervar1: " + servervar1);
final ServerInformation gameServer = new ServerInformation(name, servervar1, servervar3, servervar4, servervar5, servervar6, servervar7, ipServer, this.clientSocket_, this.out_, this.in_);
gameServer.description_ = description;
gameServer.ipToClientThread_.put(ipServer, this);
this.server_ = gameServer;
Main.servers_.put(ipServer, gameServer);
this.serverIp_ = ipServer;
break;
}
default: {
//this.logDebugMessage(0, "Unrecognized case: '" + inputLine + "', " + val);
break;
}
}
}
else if (inputLine.length() > 0) {
//this.logDebugMessage(0, "Unformated '" + inputLine + "'");
if (this.server_ != null) {
this.server_.out_.print(inputLine);
this.server_.out_.flush();
}
}
if (this.prepareTermination_) {
this.terminateThread();
return;
}
continue;
}
}
}
catch (IOException e) {
e.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
}
void logDebugMessage(final int requiredVerbose, final String msg) {
if (Main.verboseLevel_ >= requiredVerbose) {
System.out.println("[" + this.clientIp_ + "] " + msg);
}
}
void terminateThread() throws IOException {
if (!this.terminated_) {
if (this.serverIp_ != null) {
Main.servers_.remove(this.serverIp_);
}
this.clientSocket_.close();
this.in_.close();
this.out_.close();
//this.logDebugMessage(3, "Cleanup successful");
this.terminated_ = true;
}
}
}
根据JavaDocs#ConcurrentModificationException:
Note that this exception does not always indicate that an object has
been concurrently modified by a different thread. If a single thread
issues a sequence of method invocations that violates the contract of
an object, the object may throw this exception. For example, if a
thread modifies a collection directly while it is iterating over the
collection with a fail-fast iterator, the iterator will throw this
exception.
并且您在迭代此行时正在删除 Main.servers_.remove(ipServer)
:
for (final ServerInformation info2 : Main.servers_.values())
使用 ConcurrentHashMap:
Map<String, String> myMap = new ConcurrentHashMap<String, String>();
myMap.put("1", "1");
myMap.put("2", "2");
myMap.put("3", "3");
Iterator<String> it1 = myMap.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
System.out.println("Map Value:" + myMap.get(key));
if (key.equals("1")) {
myMap.remove("3");
myMap.put("4", "4");
myMap.put("5", "5");
}
}
以上可能会 return:
Map Value:1
Map Value:2
Map Value:4
Map Value:5
编辑:关于连接重置:
你的 input is null 好像掉线了。您应该始终在 readLine() 中处理无效性检查。像这样(修改为您的代码):
final String tempInputLine;
if((tempInputLine = this.in_.readLine()) == null ){
//close
this.terminateThread();
return;
}
else{
final String inputLine = tempInputLine.trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()){
//...
}
//..
}
我正在使用 Digital Ocean 服务器来促进我的 PC 游戏中的在线多人游戏。服务器是用 Java 编写的一个小应用程序。问题是服务器偶尔会关闭并在大约 15 分钟后自动重新启动。我已经升级了几次服务器,但似乎没有任何区别,最后我使用了 CPU 优化的 Droplet,具有 4 GB 内存 2 vCPUs 和 20 GB 磁盘。我不完全确定,但当大约有 15 个人在线时服务器似乎宕机了,但有时在线人数相同(或更多)并且没有发生崩溃。当大多数人在线时,它每天大约崩溃 1-2 次。
图表:
-1 分钟后服务器崩溃(晚上 7:29):https://imgur.com/a/Asit3O6
-服务器停机 12 分钟(晚上 7:41):https://imgur.com/a/ulIgTau
-服务器重新上线(晚上 7:50):https://imgur.com/a/gMOn4Jf
-服务器重新联机 28 分钟(晚上 8:18):https://imgur.com/a/lA8dufN
控制台:
-服务器崩溃后(晚上 7:39):https://imgur.com/a/h7r701H 它显示:
java.net.SocketException: Connection reset
-服务器重新上线后(晚上7:50):https://imgur.com/a/l85FYFw
我唯一认识的是 ClientThread.java 文件,它是构成服务器的 3 个 java 文件之一。 我还必须说,我对 Java 的体验非常基础,java 服务器文件是由其他人制作的(谁不可用),但我理解其中的大部分内容并自己做了一些小的调整。
为什么这个服务器偶尔会崩溃?
这是 ClientThread.java 文件:
import java.util.Iterator;
import java.io.IOException;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.Socket;
//
// Decompiled by Procyon v0.5.30
//
public class ClientThread extends Thread
{
Socket clientSocket_;
String clientIp_;
String serverIp_;
ServerInformation server_;
PrintWriter out_;
BufferedReader in_;
boolean prepareTermination_;
boolean terminated_;
private static final Pattern numberPattern;
static {
numberPattern = Pattern.compile("\d+");
}
public ClientThread(final Socket sock) {
this.clientSocket_ = sock;
this.clientIp_ = this.clientSocket_.getRemoteSocketAddress().toString();
this.serverIp_ = null;
this.server_ = null;
this.prepareTermination_ = false;
this.terminated_ = false;
}
@Override
public void run() {
try {
//this.logDebugMessage(2, "Client socket accepted, ip: " + this.clientIp_);
this.out_ = new PrintWriter(this.clientSocket_.getOutputStream(), true);
this.in_ = new BufferedReader(new InputStreamReader(this.clientSocket_.getInputStream()));
long lastActionTime = System.currentTimeMillis();
while (true) {
if (this.in_.ready() || System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
if (System.currentTimeMillis() - lastActionTime >= 1000 * Main.threadTimeout_) {
//this.logDebugMessage(3, "Thread was killed due to prolonged inactivity (" + Main.threadTimeout_ + " seconds)");
this.terminateThread();
return;
}
lastActionTime = System.currentTimeMillis();
final String inputLine = this.in_.readLine().trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()) {
final int val = Integer.parseInt(inputLine);
switch (val) {
case 111: { //send to client fast b
final StringBuilder msg = new StringBuilder();
msg.append(String.valueOf(this.in_.readLine().trim()));
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
break;
}
case 110: { //send to ip fast
final String ip = this.in_.readLine().trim();
final ClientThread target = this.server_.ipToClientThread_.getOrDefault(ip, null);
if (target != null) {
target.out_.print(this.in_.readLine().trim());
target.out_.flush();
break;
}
}
case 109: { //send to server fast
this.server_.out_.print(this.in_.readLine().trim());
this.server_.out_.flush();
break;
}
case 108: { //send to all fast
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(this.in_.readLine().trim());
thread2.out_.flush();
}
break;
}
case 107: { //send to others fast
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(this.in_.readLine().trim());
thread2.out_.flush();
}
}
break;
}
case 106: {
this.server_.description_ = this.in_.readLine().trim(); //class
break;
}
case 105: {
this.out_.print("*" + 26 + "|" + this.server_.servervar3_ + "|" + this.server_.servervar4_ + "|" + this.server_.servervar5_ + "~" + "|");
this.out_.flush();
break;
}
case 104: {
this.server_.servervar5_ = this.in_.readLine().trim(); //status
break;
}
case 103: {
this.server_.servervar3_ = this.in_.readLine().trim(); //current lap
break;
}
case 102: {
this.server_.servervar3_ = this.in_.readLine().trim(); //current lap
this.server_.servervar4_ = this.in_.readLine().trim(); //total laps
this.server_.servervar5_ = this.in_.readLine().trim(); //status
break;
}
case 101: { //admin quit server
final String ipServer = this.in_.readLine().trim();
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
this.server_ = info;
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
break;
}
case 100: {
if (System.currentTimeMillis() - this.server_.servervar2_ >= 1000 * 20) { //clients check if server is still online
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
final String ipServer = this.server_.ip_;
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
}
break;
}
case 99: {
this.server_.servervar2_ = System.currentTimeMillis(); //send server last update
break;
}
case 98: {
final String ipServer = this.in_.readLine().trim();
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
this.serverIp_ = null;
for (final ClientThread thread : this.server_.ipToClientThread_.values()) {
thread.prepareTermination_ = true;
}
this.terminateThread();
return;
}
case 96: {
final String ipServer = this.in_.readLine().trim();
final String ipClient = this.in_.readLine().trim();
//this.logDebugMessage(1, "A client wishes to connect to a server, client: " + ipClient + ", server: " + ipServer);
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
if (info == null) {
System.out.println("Connection to the server failed, no such server in the server list");
out_.print("*" + 1 + "|" + 1 + "~" + "|");
out_.flush();
break;
}
this.server_ = info;
this.server_.ipToClientThread_.put(ipClient, this);
this.server_.numplayers_ += 1;
//this.logDebugMessage(1, "Connection success");
out_.print("*" + 1 + "|" + 2 + "~" + "|");
out_.flush();
break;
}
case 95: {
final String ipClient = this.in_.readLine().trim();
this.server_.ipToClientThread_.remove(this);
this.server_.numplayers_ -= 1;
//this.logDebugMessage(1, String.valueOf(ipClient) + " disconnected from the server at " + this.server_.ip_);
this.terminateThread();
return;
}
case 94: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int i = 0; i < parseCount; ++i) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
this.server_.out_.print(msg.toString());
this.server_.out_.flush();
//this.logDebugMessage(5, "Packet for server: '" + msg.toString() + "'");
break;
}
case 93: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final String ip = this.in_.readLine().trim();
final StringBuilder msg = new StringBuilder();
for (int i = 0; i < parseCount - 1; ++i) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
final ClientThread target = this.server_.ipToClientThread_.getOrDefault(ip, null);
if (target != null) {
target.out_.print(msg.toString());
target.out_.flush();
//this.logDebugMessage(5, "Packet for " + ip + ": '" + msg.toString() + "'");
break;
}
//this.logDebugMessage(1, "Packet for " + ip + " failed to send (recipient not found)");
break;
}
case 92: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print(msg);
thread2.out_.flush();
}
//this.logDebugMessage(5, "Packet for all: '" + msg.toString() + "'");
break;
}
case 91: {
final int parseCount = Integer.parseInt(this.in_.readLine().trim());
final StringBuilder msg = new StringBuilder();
for (int j = 0; j < parseCount; ++j) {
msg.append(String.valueOf(this.in_.readLine().trim()) + "|");
}
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
if (thread2 != this) {
thread2.out_.print(msg);
thread2.out_.flush();
}
}
//this.logDebugMessage(5, "Packet for others: '" + msg.toString() + "'");
break;
}
case 90: {
//this.logDebugMessage(2, "A socket has requested the advanced server list, server list size: " + Main.servers_.size());
if (Main.servers_.size()==0) {
this.out_.print("*" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "|" + 0 + "~" + "|");
} else {
for (final ServerInformation info2 : Main.servers_.values()) {
this.out_.print("*" + String.valueOf(info2.name_) + "|" + info2.ip_ + "|" + info2.description_ + "|" + info2.servervar1_ + "|" + info2.servervar2_ + "|" + info2.servervar3_ + "|" + info2.servervar4_ + "|" + info2.servervar5_ + "|" + info2.numplayers_ + "|" + info2.ipToClientThread_.size() + "|" + info2.servervar6_ + "|" + info2.servervar7_ + "~" + "|");
if (System.currentTimeMillis() - info2.servervar2_ >= 1000 * 20) {
final String ipServer = info2.ip_;
final ServerInformation info = Main.servers_.getOrDefault(ipServer, null);
this.server_ = info;
for (final ClientThread thread2 : this.server_.ipToClientThread_.values()) {
thread2.out_.print("*" + 22 + "|" + -1 + "~" + "|");
thread2.out_.flush();
}
//this.logDebugMessage(1, "A game server has been deleted, ip: " + ipServer);
Main.servers_.remove(ipServer);
}
}
}
this.out_.flush();
break;
}
case 89: {
final String ipServer = this.in_.readLine().trim();
final String name = this.in_.readLine().trim(); //Server name
final String description = this.in_.readLine().trim(); //class
final String servervar1 = this.in_.readLine().trim(); //max players
final String servervar3 = this.in_.readLine().trim(); //current lap
final String servervar4 = this.in_.readLine().trim(); //total laps
final String servervar5 = this.in_.readLine().trim(); //status
final String servervar6 = this.in_.readLine().trim(); //Password
final String servervar7 = this.in_.readLine().trim(); //Online version
//this.logDebugMessage(1, "A game server has been registered, ip: " + ipServer + ", name: " + name + ", description: " + description + ", servervar1: " + servervar1);
final ServerInformation gameServer = new ServerInformation(name, servervar1, servervar3, servervar4, servervar5, servervar6, servervar7, ipServer, this.clientSocket_, this.out_, this.in_);
gameServer.description_ = description;
gameServer.ipToClientThread_.put(ipServer, this);
this.server_ = gameServer;
Main.servers_.put(ipServer, gameServer);
this.serverIp_ = ipServer;
break;
}
default: {
//this.logDebugMessage(0, "Unrecognized case: '" + inputLine + "', " + val);
break;
}
}
}
else if (inputLine.length() > 0) {
//this.logDebugMessage(0, "Unformated '" + inputLine + "'");
if (this.server_ != null) {
this.server_.out_.print(inputLine);
this.server_.out_.flush();
}
}
if (this.prepareTermination_) {
this.terminateThread();
return;
}
continue;
}
}
}
catch (IOException e) {
e.printStackTrace();
try {
this.terminateThread();
}
catch (IOException e2) {
e2.printStackTrace();
}
}
}
void logDebugMessage(final int requiredVerbose, final String msg) {
if (Main.verboseLevel_ >= requiredVerbose) {
System.out.println("[" + this.clientIp_ + "] " + msg);
}
}
void terminateThread() throws IOException {
if (!this.terminated_) {
if (this.serverIp_ != null) {
Main.servers_.remove(this.serverIp_);
}
this.clientSocket_.close();
this.in_.close();
this.out_.close();
//this.logDebugMessage(3, "Cleanup successful");
this.terminated_ = true;
}
}
}
根据JavaDocs#ConcurrentModificationException:
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
并且您在迭代此行时正在删除 Main.servers_.remove(ipServer)
:
for (final ServerInformation info2 : Main.servers_.values())
使用 ConcurrentHashMap:
Map<String, String> myMap = new ConcurrentHashMap<String, String>();
myMap.put("1", "1");
myMap.put("2", "2");
myMap.put("3", "3");
Iterator<String> it1 = myMap.keySet().iterator();
while (it1.hasNext()) {
String key = it1.next();
System.out.println("Map Value:" + myMap.get(key));
if (key.equals("1")) {
myMap.remove("3");
myMap.put("4", "4");
myMap.put("5", "5");
}
}
以上可能会 return:
Map Value:1
Map Value:2
Map Value:4
Map Value:5
编辑:关于连接重置:
你的 input is null 好像掉线了。您应该始终在 readLine() 中处理无效性检查。像这样(修改为您的代码):
final String tempInputLine;
if((tempInputLine = this.in_.readLine()) == null ){
//close
this.terminateThread();
return;
}
else{
final String inputLine = tempInputLine.trim();
if (ClientThread.numberPattern.matcher(inputLine).matches()){
//...
}
//..
}