Java - Язык:повторное подключение к сокету иногда выдает ошибку

StackOverflow https://stackoverflow.com/questions/674892

Вопрос

Я создаю прототип клиента и сервера, чтобы я мог понять, как обрабатывать повторные подключения.Сервер должен создать 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() возвращает сокет, я запускаю поток для обработки отправки и получения из этого сокета.Таким образом, вы будете готовы начать принимать новое подключение, как только кто-то захочет подключиться к вам.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top