programing

Server Socket accept() 메서드를 중단하려면 어떻게 해야 합니까?

newsource 2022. 8. 28. 09:43

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