#java #android #sockets #socketexception
#java #Android #сокеты #socketexception
Вопрос:
У меня есть приложение, в котором я использую сокет для прослушивания сообщений с сервера, в нем есть два действия, каждое из которых имеет свой собственный метод обработки сообщений.
Когда я запускаю второе из первого, я закрываю прослушиватель сокета для этого действия и запускаю новое во втором onCreate
методе activities. Однако, когда я переключаю действия, я получаю java.net.SocketException: Socket is closed
сообщение об ошибке.
public synchronized void run(){
//Check if the thread has been shut down
while(!this.stopped){
socket = null;
try{
//Socket
socket = new DatagramSocket(port);
//Packet
byte[] data = new byte [1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
if(!socket.isClosed()){
//Store data from socket into packet
socket.receive(packet);
//Create a string from the data
String received = new String(packet.getData(),packet.getOffset(),packet.getLength());
//Log the string TODO remove this
Log.i("RECEIVED", received);
//Get a new message object from the handler
Message msg = commandHandler.obtainMessage();
//Store the string in the message
msg.obj = received;
//Send the message to the handler
commandHandler.sendMessage(msg);
}
}catch (IOException e) {
e.printStackTrace();
}finally{
if(socket != null)
socket.close();
}
}
}
/**
* Close the listener
*/
public void shutDown(){
this.stopped = true;
if(socket != null){
socket.close();
}
}
Как вы можете видеть выше, я использую !socket.isClosed()
, чтобы проверить, закрыт ли сокет перед получением сообщения
Трассировка ошибки:
06-27 19:48:12.129: W/System.err(19460): java.net.SocketException: Socket closed
06-27 19:48:12.129: W/System.err(19460): at libcore.io.Posix.recvfromBytes(Native Method)
06-27 19:48:12.129: W/System.err(19460): at libcore.io.Posix.recvfrom(Posix.java:136)
06-27 19:48:12.129: W/System.err(19460): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
06-27 19:48:12.129: W/System.err(19460): at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
06-27 19:48:12.129: W/System.err(19460): at java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:161)
06-27 19:48:12.129: W/System.err(19460): at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:169)
06-27 19:48:12.129: W/System.err(19460): at java.net.DatagramSocket.receive(DatagramSocket.java:253)
06-27 19:48:12.129: W/System.err(19460): at com.android.homeservice.server.TabletListener.run(TabletListener.java:54)
Обновить
Итак, оказывается, что я дважды вызывал start()
метод потока во втором действии, один раз onCreate
и снова, в onStart
котором он остался от предыдущей версии кода. В любом случае спасибо за все ваши ответы и извините, если я потратил ваше время впустую
Комментарии:
1. Сокет действительно может быть закрыт после проверки, закрыт ли он, например, во время ожидания получения данных. Когда и где вы вызываете socket.close()?
2. Я вызываю метод shutDown() перед тем, как создать намерение запустить новое действие, чтобы попытаться закрыть прослушиватель предыдущих
Ответ №1:
Я бы предложил перестроить архитектуру. Держите сокет, обрабатывающий все в потоке, и просто сообщите потоку, когда он должен завершиться. Когда поток выйдет, закройте гнездо.
public synchronized void run(){
//Check if the thread has been shut down
Socket socket = new DatagramSocket(port);
while(!this.stopped){
socket = null;
try{
//Socket
//Packet
byte[] data = new byte [1024];
//Store data from socket into packet
socket.receive(packet);
//Create a string from the data
String received = new String(packet.getData(),packet.getOffset(),packet.getLength());
//Log the string TODO remove this
Log.i("RECEIVED", received);
//Get a new message object from the handler
Message msg = commandHandler.obtainMessage();
//Store the string in the message
msg.obj = received;
//Send the message to the handler
commandHandler.sendMessage(msg);
}
}catch (IOException e) {
e.printStackTrace();
}finally{
if(socket != null)
socket.close();
}
}
socket.close()
}
/**
* Close the listener
*/
public void shutDown(){
this.stopped = true;
}
Комментарии:
1.
DatagramSocket.receive()
блоки.
Ответ №2:
Очевидно, что кто-то другой закрыл его между тестом isClosed() и строкой, которая вызвала исключение.
Сделайте ‘socket’ локальной переменной, тогда никто другой не сможет ее закрыть.
Но создание сокета каждый раз вокруг цикла в первую очередь совершенно бессмысленно. Просто используйте одно и то же гнездо в течение всего срока службы нити. Если вы никогда не закроете его внутри цикла, он не сможет выдать это исключение, и вам никогда не нужно его проверять.