Почему моя программа чата работает только тогда, когда оба клиента находятся на одном компьютере?

Я изучаю UDP и создаю программу чата Клиент - Сервер - Клиент.

Он настроен так, что Сервер запускается первым и всегда ожидает некоторых команд от клиентов на порту X.

Клиент, с другой стороны, отправляет команды серверу через порт X, если он хочет войти в систему или отправить сообщение, но он прослушивает порт Y для получения входящих пакетов от сервера. Сервер, конечно, также отправляет сообщения через порт Y.

Если клиент А входит в систему (первое, что должен сделать пользователь), сервер получает имя пользователя клиента, а затем получает IP-адрес клиента на основе пакета, который он получил, и сохраняет их на карте с именем пользователя в качестве ключа.

Когда клиент B входит в систему, происходит тот же процесс. Теперь клиент A может отправлять сообщения клиенту B (и наоборот), поскольку их имена пользователей и IP-адреса хранятся на сервере.

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

Я попытался отправить клиенту несколько разных IP-адресов - один из них я получил от запуска ipconfig в командной строке, другой от поиска в Google "какой у меня IP-адрес?", Третий IP-адрес, полученный при печати на консоль. InetAddress.getLocalHost() - все эти три IP-адреса разные, и, похоже, ни один из них не работает.

На обеих машинах я зашел в брандмауэр и разрешил порты X и Y для UDP-соединений для входящих и исходящих операций. Это не похоже на помощь.

Вот мой код сервера:

    public static void main(String args[]) throws IOException{

        UDPServer SERVER = new UDPServer();

        //calls the run() method
        SERVER.start();
    }

    public UDPServer() throws IOException{

        sock = new DatagramSocket(PORT_NUMBER, InetAddress.getLocalHost());
    }

    public void run(){
        System.out.println("Waiting for Client");
        while(true){

            try{

                //========================================================================================================
                //Prepare the packet to receive data from client
                //========================================================================================================

                //Buffer (byte array) that will receive the client's data
                byte[] buffer = new byte[512];

                //Create a packet using the empty buffer and its length
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                //========================================================================================================
                //Receive the packet from the client, execute the statement, and get the result
                //========================================================================================================

                //Receive the packet
                sock.receive(packet);
                System.out.println("Server: Received packet from Client");

                //Extract the data
                String fromUser = new String(packet.getData(), 0, packet.getLength());
                //Parse data
                String[] instructions = fromUser.split(separator);

                //Add UserName and IP to tree
                if(instructions[0].equals("LOGIN")){
                    System.out.println("Logged in!");
                    nameIPTree.put(instructions[1], packet.getAddress());

                    run();
                }
                //Send message to recipient and upload to DB
                else if(instructions[0].equals("MESSAGE")){

                    //Create a string composed of the sender and the message
                    String toUser = instructions[1] + separator + instructions[3];

                    //Store the string in the buffer
                    buffer = toUser.getBytes();

                    //Make a new packet with the buffer, its length, the RECEPIENT'S IP (retrieved from tree, hence receiving user HAS TO BE LOGGED IN)
                    //and the port number the server uses

                    int add = 1;

                    packet = new DatagramPacket(buffer, buffer.length, nameIPTree.get(instructions[2]), PORT_NUMBER+add);

                    System.out.println("Sending packet from server to client at packet address: " + packet.getAddress());
                    //Send the packet
                    sock.send(packet);
                    System.out.println("Server: Sent result to Client:  " + toUser);
                }

                }
                catch (IOException /*| ClassNotFoundException | SQLException*/ e){
                    e.printStackTrace();
                    break;
                }
        }
        System.out.println("Closing the socket");
        sock.close();
    }
}

Код клиента:

    public String TalkToServer(String message){

        try{
            //========================================================================================================
            //Create a datagram socket
            //========================================================================================================
            DatagramSocket sock = new DatagramSocket();

            //========================================================================================================
            //Connect & Send to server
            //========================================================================================================

            //Create a byte array called buffer that will hold the instructions to be sent to the server
            byte[] buffer =  message.getBytes("UTF-8");

            //Get the IP address to which the packet will be sent - this is where the server is
            InetAddress ipAddress = InetAddress.getByName("123.456.78.9");//here is where I tried the different IPs;

            //Create a datagram packet which is composed of the buffer (message), its length, the IP address, 
            //and the port (matches with server's listening port) to send the data on
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, ipAddress, PORT_NUMBER);

//I know these if statements do the same - it was for testing purposes
            if(message.substring(0, 5).equals("LOGIN")){

                System.out.println("Client: Logging in");

                System.out.println("Packet's address is: " + packet.getAddress());
                //Send the packet
                sock.send(packet);
                System.out.println("Client: Sent packet to Server\nSent: " + message);

                sock.close();
                return null;
            }
            if(message.substring(0, 7).equals("MESSAGE")){

                System.out.println("Client: Sending message to server");

                //Send the packet
                sock.send(packet);
                System.out.println("Client: Sent packet to Server\nSent: " + message);

                sock.close();
                return null;
            }
        }
        catch(IOException e){System.out.print(e);}
        return null;
    }
}

А вот клиентский слушатель из моего основного класса:

    public MainGUI() throws SocketException, UnknownHostException{


        sock = new DatagramSocket(PORT_NUMBER+1, InetAddress.getLocalHost());
        System.out.println("Client listening on ip: " + InetAddress.getLocalHost());
    }
    public void run(){

        while(true){
            try {

                byte[] buffer =  new byte[512];
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

                sock.receive(packet);
                String fromUser = new String(packet.getData(), 0, packet.getLength());
                //Parse data
                String[] instructions = fromUser.split(separator);
                txtAreaConvo.append(instructions[0] + ":\t" + instructions[1]+"\n\n");


            } catch (IOException e) {   e.printStackTrace();    }

        }

}

Любая помощь на этом этапе была бы дико признательна!!!

Заранее спасибо,

Йона

1 ответ

Решение

Всякий раз, когда я занимаюсь программированием сокетов, мой первый шаг - заставить работать пакетную связь. Я использую базовую клиент-серверную реализацию и просто отправляю "Hello World", туда и обратно, чтобы убедиться, что я могу запускать все по отдельности (не localhost). Возможно, вы захотите сделать шаг назад от реализации общей программы и попытаться наладить общение, прежде чем продолжить. Это, вероятно, покажет, где лежит ваша ошибка. С учетом сказанного я попытаюсь угадать, где ваши проблемы:

Если ваша клиент-серверная связь работает до тех пор, пока вы не переключитесь на другой IP-адрес, я должен был бы предположить, что вы, как и вы, указали неправильный IP-адрес / номер порта. Убедитесь, что клиент отправляет на порт X, который прослушивает сервер. Я подозреваю, что это не твоя проблема; ваша проблема, вероятно, IP, который вы даете. whatismyip.com предоставит вам ваш публичный IP-адрес (IP-адрес, который вы должны использовать, если ваш клиент находится в другой сети), ifconfig даст вам ваш локальный IP-адрес, то есть 192.168.XX (IP-адрес, который вы должны использовать, если клиент использует ту же сеть).

В общем, я бы использовал свое первое предложение. Сделайте шаг назад и начните работать с базовыми средствами связи сервер-клиент, прежде чем пытаться решить вашу общую задачу. Если вам нужны базовые клиент-серверные программы, ознакомьтесь с примерами программирования на Java. Как только вы это устроите, я продолжу решать вашу общую задачу. Это поможет вам сузить проблему и, возможно, решить ее.

Другие вопросы по тегам