#java #multithreading #sockets #tcp #serversocket
#java #многопоточность #сокеты #tcp #serversocket
Вопрос:
Я внедряю очень простой API, чтобы иметь лучший контроль над ServerSocket и сокетами, но у меня очень странная проблема, которую я не могу решить из-за недостатка знаний о потоках. Позвольте мне объяснить это.
В моем классе SocketStreamReceiver я использую вторичный поток для прослушивания новых сокетов с помощью ServerSocket#accept()
. Существует 2 метода: start() и stop(), которые клиент может использовать для запуска (создания потока и начала прослушивания с accept()
) и остановки (закрытия ServerSocket и уничтожения потока) моего SocketStreamReceiver.
Как вы будете реализовывать метод stop()?Имейте в виду, что stop() может быть вызван внутри doSomething() в том же вторичном потоке, запущенном start(). Вы можете изменить все, что хотите: вы можете создать ServerSocket внутри потока, если хотите, непосредственно перед while (запуск).
public class SocketStreamReceiver{
...
private Thread thread;
private ServerSocket server;
private boolean running;
...
public void start () throws IOException{
if (thread != null) return;
server = new ServerSocket (port);
thread = new Thread (new Runnable (){
@Override
public void run (){
try{
while (running){
Socket socket = server.accept ();
doSomething (socket);
}
}catch (SocketException e){
...
}catch (IOException e){
...
}
}
}, "SocketStreamReceiver");
thread.start ();
}
public void stop () throws IOException{
if (thread == null) return;
//code...
thread = null;
}
}
Спасибо.
РЕДАКТИРОВАТЬ — Решение:
public class SocketStreamReceiver{
private Thread thread;
private ServerSocket server;
private volatile boolean running;
...
public synchronized void start () throws IOException{
if (thread != null) throw new IllegalStateException ("The receiver is already started.");
server = new ServerSocket (port);
thread = new Thread (new Runnable (){
@Override
public void run (){
try{
running = true;
while (running){
doSomething (server.accept ());
...
}
}catch (SocketException e){
...
}catch (IOException e){
...
}
}
}, "SocketStreamReceiver");
thread.start ();
}
public synchronized void stop (){
if (thread == null) return;
running = false;
try{
if (server != null){
server.close ();
}
}catch (IOException e){}
thread = null;
}
}
Ответ №1:
Я бы просто сделал
public void stop() {
running = false;
try{
if (server != null) server.close ();
} catch (IOException ignored){
}
}
Похоже, вам даже не нужен флаг running. Однако я бы использовал это в коде принятия вашего сервера, чтобы определить, ожидается исключение или нет. т. Е. при запуске == false игнорируйте все исключения.
Я бы сделал running
volatile.
Я бы синхронизировал start () / stop (), если вы можете запускать их из разных потоков.
Комментарии:
1. Если вызывается server.close() и после того, как мы выполним server.accept(), что произойдет? Блокирует ли ServerSocket поток?
2. Accept() вызовет исключение SocketException, которое вам все равно придется перехватить.
3. Почему вы перехватываете исключение И генерируете его?
4. @MByD, потому что я забыл его удалить. Спасибо.