Java — как я могу проверить, отредактировал ли ServerSocket.accept () соединение?

#java #multithreading #sockets #server #client-server

#java #многопоточность #сокеты #сервер #клиент-сервер

Вопрос:

Я пытаюсь написать простое решение для чата сервер-клиент. В целях тестирования я создаю массив из 2 серверных потоков, которые отвечают за отправку и получение сообщений от подключенных клиентов.

Я бы хотел, чтобы сервер отклонял соединения после того, как количество подключенных клиентов достигнет максимального значения. Однако, даже если сервер не принимает соединение, сокет на стороне клиента создается. Методы сокета.isBound и isConnected оба возвращают истинное значение.

Итак, вернемся к основному вопросу. Есть ли у вас какие-либо идеи, как я мог бы отклонить подключение клиента, когда ServerSocket не сможет .accept () дополнительного подключения?

Вот код класса Server.

 public class Server {

private ServerSocket serverSocket = null;
private ServerThread serverThread[] = new ServerThread[2];
protected volatile int clientCount = 0;

public Server (int port){
   try {
       System.out.println("Binding to port "   port   " ...");
       serverSocket = new ServerSocket (port);
       System.out.println("Binded to port "   port   ".");
   } catch (IOException e) {
       System.out.println("Failed binding to the port: "   e.getMessage());
        }
}

public void addThread (Socket socket){

   System.out.println ("Client connected at socket: "   socket);
   serverThread[clientCount] = new ServerThread (this, socket);
   try {
       serverThread[clientCount].open();
       serverThread[clientCount].start();
   } catch (IOException e) {e.getMessage();}

}

public void waitForClient () {

   boolean isLogPrinted = false;

   while (true){
       try {
           if (clientCount < serverThread.length){
               System.out.println ("Waiting for connection...");
               isLogPrinted = false;
               addThread (serverSocket.accept());
               clientCount  ;
               System.out.println("Client count: "   clientCount);
           }
           else {
               if (!isLogPrinted){
                    System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! ("   clientCount   ").");
                    isLogPrinted = true;
               }
           }
       } catch (IOException e) {
           System.out.println("Error while waiting for new clients to connect: "   e.getMessage());
            }
   }
}

public synchronized void broadcastMessages (String msg){
   for (int i = 0; i < clientCount; i  )
       serverThread[i].sendMessage(msg);
}

public static void main (String args[]){
   Server server = new Server (4200);
   server.waitForClient();
 }

}
  

Комментарии:

1. Если вы не покажете свой клиентский код, на ваш вопрос будет сложно или невозможно ответить.

2. @PresidentJamesMoveonPolk явно нет. Здесь вам не нужно ничего большего, чем подключающийся клиент. Больше ничего не нужно делать. Подойдет Telnet.

3. Ваш заголовок не соответствует вашему вопросу. Пожалуйста, уточните.

Ответ №1:

Я бы хотел, чтобы сервер отклонял соединения после того, как количество подключенных клиентов достигнет максимального значения.

Закройте серверный сокет.

Однако, даже если сервер не принимает соединение, сокет на стороне клиента создается. Методы socket.isBound и isConnected оба возвращают истинное значение.

Правильно. Это потому, что TCP поддерживает «очередь невыполненных» входящих подключений, которые были завершены, но еще не приняты серверным приложением.

Итак, вернемся к основному вопросу. Есть ли у вас какие-либо идеи, как я мог бы отклонить подключение клиента, когда ServerSocket не сможет .accept () дополнительного подключения?

Закройте сокет сервера, пока количество подключений максимально.

Однако из-за невыполненной работы этот метод никогда не может быть идеальным. Идеального решения не существует. Вы могли бы заставить сервер немедленно закрыть лишние соединения, но лишние клиенты не обнаружат этого, пока не попытаются что-то отправить. Если вам нужно совершенство, вам, вероятно, придется ввести протокол приложения, посредством которого сервер отправляет что-то вроде «ПРИНЯТО» или «ОТКЛОНЕНО» соответственно.

Ответ №2:

Вместо while true в вашем методе waitForClient попробуйте это

 private final int allowedClients = 10;
private int connectedClients = 0;
public void waitForClient () {

boolean isLogPrinted = false;

while (connectedClients <= allowedClients){
    try {
       if (clientCount < serverThread.length){
           System.out.println ("Waiting for connection...");
           isLogPrinted = false;
           addThread (serverSocket.accept());
           connectedClients  ;
           System.out.println("Client count: "   clientCount);
       }
       else {
           if (!isLogPrinted){
                System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! ("   clientCount   ").");
                isLogPrinted = true;
           }
       }
   } catch (IOException e) {
       System.out.println("Error while waiting for new clients to connect: "   e.getMessage());
        }
  

}
}

Комментарии:

1. Хорошо, но проблема по-прежнему остается той же. Сокет на стороне клиента по-прежнему создается без каких-либо проблем, даже несмотря на то, что соединение не было принято сервером. Я ищу способ проверить, совершил ли сервер действие server.accept().

2. Если вы прочитаете условие цикла после достижения максимального количества клиентов, сервер просто перестанет прослушивать дальнейшие соединения, и в конечном итоге клиенты не смогут подключиться

3. Предоставленное мной решение также останавливает ServerSocket от .accept () входящих подключений. Дело в том, что сокет на стороне клиента по-прежнему создается без каких-либо исключений. Почему это происходит, когда ServerSocket не принял соединение?

4. Этот код будет бездумно вращаться, если условие ложно, По крайней мере, добавьте в него режим ожидания. Смысл проведения двух тестов ускользает от меня.

Ответ №3:

Я знаю, что отвечать на этот вопрос очень поздно, но я думаю, что это поможет многим. Вы можете проверить наличие существующего сокета, если таковой имеется, с помощью приведенного ниже кода.

 SocketAddress socketAddress = new InetSocketAddress("localhost", 8091);
    Socket socket = new Socket();
    ServerSocket serverSocket = null;
    try {
        socket.connect(socketAddress);
    } catch (IOException e) {
        e.printStackTrace();
    }
    if(socket == null) {
        try {
            serverSocket = new ServerSocket(8091);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  

если не найден активный сокет на том же порту и IP, то он запустит новый серверный сокет, или вы можете изменить его, только запустив сокет, иначе вы сможете подключиться к существующему сокету.

Комментарии:

1. Никак не отвечает на заданный вопрос. Прочитайте вопрос, прежде чем отвечать.