很难把它放在标题中,但是每次客户端断开连接时,都会抛出很多异常,并且服务器在DC之后不允许任何更多连接。下面是我得到的错误:
java.net.SocketException: Socket closed
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at ClientHandler.setupStreams(ClientHandler.java:34)
at ClientHandler.run(ClientHandler.java:22)
现在我期望得到这个异常,因为…客户端关闭了服务器与客户端的连接。处理步骤但是我不能理解的是为什么客户端在第一次断开连接后不允许连接。我假设它打破了while循环,但为什么呢?下面的代码接收客户端连接,接受它并将其传递给处理程序类:
public class ClientConnector
{
public static JTextField userText;
public static JTextArea chatWindow;
public static int Connections = 0;
public static Vector sendQueue = new Vector();
public static ArrayList<ObjectOutputStream> Streams = new ArrayList<ObjectOutputStream>();
public static Scanner input = new Scanner(System.in);
public ClientConnector()
{
}
public static void runServer()
{
try
{
System.out.println("[Info] Attempting to bind to port 1337.");
@SuppressWarnings("resource")
ServerSocket serversocket = new ServerSocket(1337);
System.out.println("[Info] Bound to port 1337.");
System.out.println("[Info] Waiting for client connections...");
while(true)
{
Socket socket = serversocket.accept();
new ClientHandler(socket).start();
Connections += 1;
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
这相当简单。下面是处理客户端连接的代码:
public class ClientHandler extends Thread
{
Socket ConnectedClient;
static ObjectOutputStream Output;
static ObjectInputStream Input;
public static boolean isError = false;
public static int updateCounter = 0;
ClientHandler(Socket socket)
{
ConnectedClient = socket;
}
public void run()
{
while(true)
{
setupStreams();//22
WhileChatting();
}
}
public void setupStreams()
{
try
{
if(isError == false)
{
Output = new ObjectOutputStream(ConnectedClient.getOutputStream());
Input = new ObjectInputStream(ConnectedClient.getInputStream());//34
ClientConnector.Streams.add(Output);
}
}
catch (IOException e)
{
isError = true;
e.printStackTrace();
}
}
public static void WhileChatting()
{
String Message = "";
do
{
try
{
if(isError == false)
{
Message = (String)Input.readObject();
for(int i = 0; i < ClientConnector.Streams.size(); i++)
{
ClientConnector.Streams.get(i).writeObject(Message);
System.out.println(Message);
}
}
}
catch(ClassNotFoundException CNFE)
{
isError = true;
CNFE.printStackTrace();
}
catch(EOFException eof)
{
for(int i = 0; i < ClientConnector.Streams.size(); i++)
{
try
{
Output.close();
Input.close();
ClientConnector.Streams.get(i).close();
ClientConnector.Streams.remove(i);
System.out.println("Connection lost");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
catch (IOException e)
{
isError = true;
e.printStackTrace();
}
}
while(Message != "/disconnect");
}
public static void sendMessage(String message)
{
try
{
if(isError == false)
{
Output.writeObject(message);
System.out.println(message);
}
}
catch(IOException Ex)
{
isError = true;
Ex.printStackTrace();
}
}
public static void sendServerMessage(String message)
{
int Limit = 0;
try
{
for(int i = 0; i < ClientConnector.Streams.size(); i++)
{
if(Limit == 0)
{
ClientConnector.Streams.get(i).writeObject("247c[Server] 247d" + message);
System.out.println("247c[Server] 247d" + message);
Limit = 1;
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void closeConnections()
{
try
{
if(isError == false)
{
Output.close();
Input.close();
//ConnectedClient.close();
}
}
catch(IOException Ex)
{
isError = true;
Ex.printStackTrace();
}
}
}
我在受影响的行中进行了注释。客户端断开连接后出现错误。我不知道它是导致while循环中断的异常还是其他的东西。如何使此代码在客户端断开连接后继续允许传入连接?我试过调试和使用System.out.println。
现在我期望得到这个异常,因为…日志含义客户端关闭了服务器和客户端之间的连接。
。此异常意味着您关闭 Socket
,然后尝试对其进行进一步的I/O。与peer无关。
但是我不明白的是为什么客户端在第一次断开连接后不允许连接。
你的代码有很多问题。
-
对于
Socket
的寿命,必须在两端使用相同的ObjectInputStream
和ObjectOutputStream
。目前,您正在创建一个新的对,并将它们添加到数据结构中,每次循环。 -
当您在一个
Socket
上捕获EOFException
时,您正在关闭所有套接字。你应该只关闭一个,你得到异常的那个,然后你必须打破所有的循环,并允许线程退出。 -
你应该基本上改变你的
while
循环从while (true)
到while (!isError)
和停止测试isError
在其他地方。我将去掉whileChatting
方法,并将其合并到这个while循环中。你不需要内部的do
循环。你只需要一个循环读取到EOS或断开连接命令。