Java - Язык:повторное подключение к сокету иногда выдает ошибку
-
21-08-2019 - |
Вопрос
Я создаю прототип клиента и сервера, чтобы я мог понять, как обрабатывать повторные подключения.Сервер должен создать serversocket и прослушивать вечно.Клиент может подключиться, отправить свои данные и закрыть свой сокет, но он не будет отправлять на сервер сообщение типа "Я закончил и закрываюсь".По этой причине сервер получает EOFException
когда это делает readByte()
поскольку удаленный клиент закрылся.В обработчике ошибок для EOFException
, это закроет сокет и откроет новый.
Вот в чем проблема:Клиент иногда получает SocketWriteError
когда это делает outputStream.write()
вызывайте даже после того, как он успешно откроет сокет /inputstream /outpustream.Возможно, это как-то связано с частотой, с которой я открываю и закрываю эти сокеты.Одна интересная вещь заключается в том, что клиент выполняет произвольное количество операций записи / закрытия / повторного подключения, прежде чем отключиться.Иногда он выходит из строя при первом повторном подключении, в других случаях требуется 50 повторных подключений, прежде чем увидеть SocketWriteError
.
Вот ошибка на стороне клиента:
java.net.SocketException: Connection reset by peer: socket write error at java.net.SocketOutputStream.socketWrite0(Native Method) at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92) at java.net.SocketOutputStream.write(SocketOutputStream.java:115) at bytebuffertest.Client.main(Client.java:37)
Вот несколько фрагментов кода:
СЕРВЕР:
public static void main(String[] args)
{
Server x = new Server();
x.initialize();
}
private void initialize()
{
ServerSocket s;
InputStream is;
DataInputStream dis;
while (true) //ADDED THIS!!!!!!!!!!!!!!!!!!!!!!
{
try
{
s = new ServerSocket(4448);
s.setSoTimeout(0);
s.setReuseAddress(true);
is = s.accept().getInputStream();
System.out.println("accepted client");
dis = new DataInputStream(is);
try
{
byte input = dis.readByte();
System.out.println("read: " + input);
} catch (Exception ex)
{
System.out.println("Exception");
dis.close();
is.close();
s.close();
}
} catch (IOException ex)
{
System.out.println("ioexception");
}
}
}
КЛИЕНТ:
public static void main(String[] args)
{
Socket s;
OutputStream os;
try
{
s = new Socket("localhost", 4448);
s.setKeepAlive(true);
s.setReuseAddress(true);
os = s.getOutputStream();
int counter = 0;
while (true)
{
try
{
os.write((byte) counter++);
os.flush();
os.close();
s.close();
s = new Socket("localhost", 4448);
s.setKeepAlive(true);
s.setReuseAddress(true);
os = s.getOutputStream();
} catch (Exception e)
{
e.printStackTrace();
System.err.println("ERROR: reconnecting...");
}
}
} catch (Exception ex)
{
ex.printStackTrace();
System.err.println("ERROR: could not connect");
}
}
Кто-нибудь знает, как правильно переподключиться?
Решение
Не закрывайте ServerSocket при ошибке, просто .accept() новое соединение.
Что я обычно делаю, так это каждый раз, когда ServerSocket.accept() возвращает сокет, я запускаю поток для обработки отправки и получения из этого сокета.Таким образом, вы будете готовы начать принимать новое подключение, как только кто-то захочет подключиться к вам.