Server Socket accept() 메서드를 중단하려면 어떻게 해야 합니까?
내 주요 실에는while(listening)
호출하는 루프accept()
나의 위에ServerSocket
오브젝트는 새로운 클라이언트스레드를 시작하여 새로운 클라이언트가 받아들여질 때 컬렉션에 추가합니다.
명령어를 발행하기 위해 사용하는 관리 스레드도 있습니다.'exit'
false를 리슨함으로써 모든 클라이언트스레드가 셧다운되고 그 자체가 셧다운되며 메인스레드가 셧다운됩니다.
하지만, 그accept()
을 호출하다while(listening)
루프 블록은 중단시킬 방법이 없는 것 같기 때문에 상태를 다시 확인할 수 없고 프로그램을 종료할 수 없습니다!
더 좋은 방법이 있을까요?아니면 차단 방법을 방해할 수 있는 방법이 있을까요?
다른 스레드에서 콜할 수 있으며 콜은 를 슬로우합니다.
시간 초과 설정accept()
지정된 시간이 경과하면 콜은 블로킹을 타임아웃합니다.
http://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
차단 시간 제한 설정
Socket
조작:ServerSocket.accept(); SocketInputStream.read(); DatagramSocket.receive();
이 옵션을 활성화하려면 차단 작업을 시작하기 전에 설정해야 합니다.타임아웃이 만료되어 작업이 계속 차단되면
java.io.InterruptedIOException
인스톨 됩니다.그Socket
이 경우 닫히지 않습니다.
호출중close()
에서ServerSocket
선택사항이 있나요?
http://java.sun.com/j2se/6/docs/api/java/net/ServerSocket.html#close%28%29
이 소켓을 닫습니다.accept()에서 현재 차단된 스레드는 SocketException을 슬로우합니다.
break server socket.accept()용 "void" 소켓을 작성하기만 하면 됩니다.
서버측
private static final byte END_WAITING = 66;
private static final byte CONNECT_REQUEST = 1;
while (true) {
Socket clientSock = serverSocket.accept();
int code = clientSock.getInputStream().read();
if (code == END_WAITING
/*&& clientSock.getInetAddress().getHostAddress().equals(myIp)*/) {
// End waiting clients code detected
break;
} else if (code == CONNECT_REQUEST) { // other action
// ...
}
}
서버 사이클을 중단하는 방법
void acceptClients() {
try {
Socket s = new Socket(myIp, PORT);
s.getOutputStream().write(END_WAITING);
s.getOutputStream().flush();
s.close();
} catch (IOException e) {
}
}
이유ServerSocket.close()
예외가 발생하는 이유는outputstream
또는inputstream
콘센트에 접속되어 있습니다.먼저 입력 스트림과 출력 스트림을 닫으면 이 예외를 안전하게 방지할 수 있습니다.그런 다음 닫기를 닫아보세요.ServerSocket
다음은 예를 제시하겠습니다.
void closeServer() throws IOException {
try {
if (outputstream != null)
outputstream.close();
if (inputstream != null)
inputstream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
if (!serversock.isClosed())
serversock.close();
}
}
이 메서드를 호출하면 어디에서나 예외 없이 소켓을 닫을 수 있습니다.
server Socket을 사용합니다.set So Timeout(timeout In Millis).
좋아, 작전부 질문에 좀 더 직접적으로 대답할 수 있는 방식으로 이 일을 진행시켰어
사용 방법에 대한 스레드 예제를 보려면 짧은 답변 이후에도 계속 읽어 보십시오.
간단한 답변:
ServerSocket myServer;
Socket clientSocket;
try {
myServer = new ServerSocket(port)
myServer.setSoTimeout(2000);
//YOU MUST DO THIS ANYTIME TO ASSIGN new ServerSocket() to myServer‼!
clientSocket = myServer.accept();
//In this case, after 2 seconds the below interruption will be thrown
}
catch (java.io.InterruptedIOException e) {
/* This is where you handle the timeout. THIS WILL NOT stop
the running of your code unless you issue a break; so you
can do whatever you need to do here to handle whatever you
want to happen when the timeout occurs.
*/
}
실제의 예:
이 예에서는 스레드 내부에서 연결을 기다리는 ServerSocket이 있습니다.앱을 닫을 때는 앱을 닫기 전에 스레드(구체적으로는 소켓)를 깔끔하게 셧다운하고 싶기 때문에 ServerSocket의 .setSoTimeout()을 사용하여 타임아웃 후 발생하는 인터럽트를 사용하여 부모가 스레드를 셧다운하려고 하는지 확인합니다.이 경우 소켓을 닫고 스레드가 완료되었음을 나타내는 플래그를 설정한 후 스레드 루프에서 분리하여 null을 반환합니다.
package MyServer;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import javafx.concurrent.Task;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
public class Server {
public Server (int port) {this.port = port;}
private boolean threadDone = false;
private boolean threadInterrupted = false;
private boolean threadRunning = false;
private ServerSocket myServer = null;
private Socket clientSocket = null;
private Thread serverThread = null;;
private int port;
private static final int SO_TIMEOUT = 5000; //5 seconds
public void startServer() {
if (!threadRunning) {
serverThread = new Thread(thisServerTask);
serverThread.setDaemon(true);
serverThread.start();
}
}
public void stopServer() {
if (threadRunning) {
threadInterrupted = true;
while (!threadDone) {
//We are just waiting for the timeout to exception happen
}
if (threadDone) {threadRunning = false;}
}
}
public boolean isRunning() {return threadRunning;}
private Task<Void> thisServerTask = new Task <Void>() {
@Override public Void call() throws InterruptedException {
threadRunning = true;
try {
myServer = new ServerSocket(port);
myServer.setSoTimeout(SO_TIMEOUT);
clientSocket = new Socket();
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
clientSocket = myServer.accept();
}
catch (java.io.InterruptedIOException e) {
if (threadInterrupted) {
try { clientSocket.close(); } //This is the clean exit I'm after.
catch (IOException e1) { e1.printStackTrace(); }
threadDone = true;
break;
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
};
}
그런 다음 컨트롤러 클래스에서... (관련 코드만 표시하고 필요에 따라 자신의 코드로 마사지합니다.)
public class Controller {
Server server = null;
private static final int port = 10000;
private void stopTheServer() {
server.stopServer();
while (server.isRunning() {
//We just wait for the server service to stop.
}
}
@FXML private void initialize() {
Platform.runLater(()-> {
server = new Server(port);
server.startServer();
Stage stage = (Stage) serverStatusLabel.getScene().getWindow();
stage.setOnCloseRequest(event->stopTheServer());
});
}
}
이게 앞으로 누군가에게 도움이 됐으면 좋겠어요.
보다 깔끔한 방법은 Accept 루프에서 플래그를 체크한 후 관리 스레드가 Accept에서 스레드블로킹을 종료할 경우 플래그를 설정하고(스레드 세이프), 클라이언트소켓 접속을 리스닝 소켓에 확립하는 것입니다.accept를 실행하면 블로킹이 중지되고 새로운 소켓이 반환됩니다.리스닝 스레드가 스레드를 깔끔하게 종료하도록 하는 간단한 프로토콜 문제를 해결할 수 있습니다.다음으로 클라이언트 측 소켓을 닫습니다.예외는 없습니다. 훨씬 깨끗합니다.
accept 함수를 호출하는 동안 파라미터로서 타임아웃 제한(밀리초)을 전달하기만 하면 됩니다.
예를 들어 serverSocket.accept(1000), 1초 후에 자동으로 요청을 닫습니다.
언급URL : https://stackoverflow.com/questions/2983835/how-can-i-interrupt-a-serversocket-accept-method
'programing' 카테고리의 다른 글
Vuex는 개발 도구를 통해 수동으로 커밋될 때까지 변경을 커밋하지 않습니다. (0) | 2022.08.28 |
---|---|
Java에서 Enum start 값을 설정할 수 있습니까? (0) | 2022.08.28 |
Vue 3: 부모 컴포넌트에서 자녀 컴포넌트로 이벤트 전송 (0) | 2022.08.28 |
Vue: 프로펠러 함수의 기본값 (0) | 2022.08.28 |
반복기 없이 Set/HashSet에서 반복하는 방법 (0) | 2022.08.27 |