Как открыть сокет Java - PullRequest
0 голосов
/ 30 июля 2009

Я читаю из Java Socket в цикле.

Я хочу снова открыть сокет, если чтение вызывает исключение.

В попытке проверить это, я просто закрываю сокет и ловлю исключение.

Подвох в том, когда я пытаюсь снова открыть сокет:

serverSocket = new ServerSocket(port)
socket = serverSocket.accept()

выдает исключение:

java.net.BindException: The socket name is already in use

Это немедленная проблема для тестирования. Но это может произойти и в производстве.

Как можно надежно восстановить, открыв новое сокетное соединение, после исключения был брошен?

Ответы [ 4 ]

5 голосов
/ 30 июля 2009

Извините, если я неправильно понимаю, что вы говорите.

В случае сбоя метода read () в сокете это не закроет ServerSocket.

Вы по-прежнему сможете вызывать serverSocket.accept (), не создавая новый. Я думаю, именно поэтому вы получаете BindException.

4 голосов
/ 30 июля 2009

Вам нужно создать серверный сокет один раз и передать любой принятый сокет его обработчику - обычно это делается в другом потоке.

Ошибка, которую вы получаете, потому что вы пытаетесь прослушивать один и тот же порт дважды, что невозможно.

Эта статья может вам помочь. Вот один из примеров кода:

public void await() {
    ServerSocket serverSocket = null;
    int port = 8080;
    try {
        serverSocket =  new ServerSocket(port, 1,
        InetAddress.getByName("127.0.0.1"));
    }
    catch (IOException e) {
        e.printStackTrace();
        System.exit(1);
    }

    // Loop waiting for a request
    while (!shutdown) {
        Socket socket = null;
        InputStream input = null;
        OutputStream output = null;
        try {
            socket = serverSocket.accept();
            input = socket.getInputStream();
            output = socket.getOutputStream();

            // create Request object and parse
            Request request = new Request(input);
            request.parse();

            // create Response object
            Response response = new Response(output);
            response.setRequest(request);
            response.sendStaticResource();

            // Close the socket
            socket.close();

            //check if the previous URI is a shutdown command
            shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
        }
        catch (Exception e) {
            e.printStackTrace();
            continue;
        }
    }
}
2 голосов
/ 31 июля 2009

То, что я нашел для работы, было так:

  1. Закрыть серверный сокет
  2. Создать новый ServerSocket

После закрытия ServerSocket не потребовалось никаких задержек. Это на машине IBM AIX - возможно, на других платформах поведение другое.

Не было необходимости закрывать гнездо.

Я также добавил тайм-аут в сокет для восстановления после сбоя соединения на другом конце. Вот код, который запускается при запуске и при исключении:

if (serverSocket != null) serverSocket.close();
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();
socket.setSoTimeout(TIMEOUT);
is = socket.getInputStream();

Спасибо также за подсказку закрыть ServerSocket. Это сделало меня на правильном пути. А также за полезные ссылки по сетевому программированию.

0 голосов
/ 30 июля 2009

вы должны закрыть сокет, когда возникла исключительная ситуация во время сеанса соединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...