У меня есть java.nio.channels.ServerSocketChannel
который я инициализировал следующим образом:
while(true)
{
ServerSocketChannel channel = ServerSocketChannel.open();
InetSocketAddress serverSocket = new InetSocketAddress(host,port);
channel.bind(serverSocket);
SocketChannel ch = channel.accept();
// Later on when I have read off data from a client, I want to shut this
// connection down and restart listening.
channel.socket().close(); //Just trying to close the associated socket
// too because earlier approaches failed
channel.close();
}
Когда я отправляю первое сообщение от клиента, он успешно доставляется на сервер, и клиентская программа завершается. Тогда начинаются неприятности. Когда я снова инициализирую клиента и пытаюсь установить в том же порту и адресе сервера, как и в первый раз, я получаю
java.net.BindException: адрес уже используется: connect
исключение, хотя я закрыл связанный канал/сокет. Я обновляю объекты ServerSocketChannel
и InetSocketAddress
потому что, поскольку мой клиентский экземпляр должен отключиться после записи, я должен отключить этот канал, и поскольку я не могу повторно использовать канал после его закрытия, я должен каждый раз создавать новый объект. Моя теория с тех пор, как ссылка на channel
переназначается каждый раз, осиротевший объект становится GC-мясом, но поскольку метод close(), по-видимому, не работает должным образом, канал все еще жив, и пока GC не собирает его, мой порт будет запутан. Тем не менее я попытался сохранить инициализацию объектов ServerSocketChannel
и InetSocketAddress
до цикла while, но это не помогло, и такое же исключение произошло после первой записи, как и раньше.
ServerSocketChannel channel = ServerSocketChannel.open();
InetSocketAddress serverSocket = new InetSocketAddress(host,port);
channel.bind(serverSocket);
while (true)
{
SocketChannel ch = channel.accept();
//read from a client
}
Для ясности, вот как я подключаюсь от клиента:
SocketChannel ch=SocketChannel.open();
ch.bind(new InetSocketAddress("localhost", 8077));
InetSocketAddress address=new InetSocketAddress("localhost",8079);
//the address and port of the server
System.out.print(ch.connect(address));
ByteBuffer buf=ByteBuffer.allocate(48);
buf.clear();
buf.put("Hellooooooooooooooooooooooooo".getBytes());
buf.flip();
while(buf.hasRemaining()) {
ch.write(buf);
}
ch.close();
Похоже, вы запутываете клиента и сервер. Обычно сервер запускается только один раз и bind
к порту s. Как правило, нет необходимости close
что-либо, поскольку порт освобождается при выходе из программы. Очевидно, вы должны закрыть Socket
полученный ServerSocket.accept()
, но это другая история.
Я думаю, вы запутались в своих именах переменных (как это случилось со мной, когда я начал с этого). Попытайтесь назвать все по своему типу, здесь венгерский действительно помог мне.
Код, который я написал для тестирования, длинный, глупый и скучный. Но, похоже, это работает.
сделайте ch.close(), а также GC-клиент.
ServerSocketChannel
похоже, работает. Даже некоторое общение делает. Я свяжу это, когда немного отполирую.