当前位置: 首页 > 知识库问答 >
问题:

为什么我的聊天程序只有在两个客户端都在同一台机器上时才起作用?

阎宾实
2023-03-14

我正在学习一些UDP并且正在创建一个客户端-服务器-客户端聊天程序。

它的设置方式是服务器首先运行,并且始终侦听来自端口X上的客户端的一些命令。

另一方面,如果客户机想要登录或发送消息,它在端口X上向服务器发送命令,但是它在端口Y上监听来自服务器的传入数据包。当然,服务器也在端口Y上发送消息。

如果客户端A登录(用户必须做的第一件事),服务器会接收客户端的用户名,然后根据收到的数据包获取客户端的IP,并将两者都存储在以用户名为密钥的地图中。

当客户端B登录时,会发生相同的过程。现在,客户端A可以向客户端B发送消息(反之亦然),因为它们的用户名和IP都存储在服务器中。

当两个客户端都在同一台机器上时,这一切都很好,但是一旦我尝试在不同的机器上运行客户端B,数据包似乎永远不会到达服务器。没有错误,程序不会崩溃,但服务器永远不会收到任何东西。

我尝试了一堆不同的ip让客户端发送到-一个是我在命令行上运行“ipconfig”得到的,另一个是通过谷歌搜索“我的ip地址是什么?”得到的,我从控制台InetAddress打印出来的第三个IP。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;
    }
}

下面是我的Main类中的客户端监听器:

    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个答案

祁承望
2023-03-14

每当我进行套接字编程时,我的第一步就是让包通信工作起来。我使用一个基本的客户机-服务器实现,简单地来回发送“Hello World ”,以确保我可以单独运行所有东西(不是本地主机)。您可能想从实施整个计划中后退一步,并尝试在继续之前进行沟通。这可能会显示您的问题所在。话虽如此,我还是试着猜猜你的问题在哪里:

如果你的客户机-服务器通信正常,直到你换了一个不同的IP地址,那么我会像你一样认为你给了错误的IP地址/端口号。确保客户端发送到服务器正在监听的端口X。我怀疑这不是你的问题;你的问题很可能是你给的IP。whatismyip.com将提供您的公共IP地址(如果您的客户端在不同的网络上,您应该使用的IP地址),ifconfig将提供您的本地IP地址,即192.168.X.X(如果客户端使用相同的网络,您应该使用的IP地址)。

总而言之,我会使用我的第一个建议。退一步,在尝试解决您的总体目标之前,让基本的服务器-客户端通信正常工作。如果您需要一些基本的客户端-服务器程序,请查看Java套接字编程示例。一旦您使这些工作正常,我将继续解决您的总体目标。这将帮助您缩小问题范围,并可能解决它。

 类似资料:
  • 我想在java上创建一个客户机/服务器应用程序,服务器的IP地址为192.168.1.100,在端口4500上等待客户机请求。 客户端从键盘上读取字符串,向服务器发送连接请求。一旦建立了连接,它就会将字符串发送到服务器。 这是我尝试的代码: 对于服务者: 对于客户端: 但这段代码有一个问题:

  • 问题内容: 这是完整的代码: 什么也没出现。但是,如果我删除第一行(),则所有页面都是绿色的。 我有两个问题: 如何在不删除标签的情况下填写页面? 为什么要删除使其起作用? 问题答案: CSS 属性,百分比值和DOCTYPE 问题的 第一部分 询问如何对您的身高施加100%的高度,其他人多次回答。本质上,在根元素上声明高度: 问题的 第二部分 受到的关注要少得多。我会尽力回答。 为什么去除make

  • 我已经找了好几天了,想为我的问题找到一些解决办法,在我看来不是太难,但显然是无法解决的问题。 我有一个EAR项目,其中包含一些EJB、一个web客户机(工作正常),现在我添加了一个应用程序客户机模块。 由于所有内容都在同一个项目中,我认为在应用程序客户机的主类中进行简单的@EJB注入就可以了。我还尝试了JNDI查找。我使用eclipse和glassfish作为服务器,并尝试运行应用程序1。在ecl

  • 我对python有点陌生,这是我第一次使用套接字,我试图制作一个具有客户端和服务器的应用程序,用户可以在客户端中输入,它将被发送到服务器,然后将其发送给所有其他客户端。我已经将其设置为工作状态,但每当我尝试发送第二条消息时,我总是收到一个错误错误:[Errno 10058]发送或接收数据的请求被禁止,因为套接字已经在之前的关闭调用中关闭了该方向。我如何才能做到这一点? 尝试在启动新套接字或发送新消

  • 问题内容: 我刚刚开始学习NodeJS和Socket.io。到目前为止,我已经从socket.io官方网站获得了这个演示代码: http://socket.io/demos/chat/ 我能够获得所连接的每个用户(套接字)的唯一客户端ID,但我仍在设法弄清楚,如何使我的代码在某人运行该应用程序时一次只能与1个随机用户连接。我只想像Omegle(http://www.omegle.com/)那样进行

  • 我需要在netty中有一个客户机/服务器通信,用于我的项目目的之一。所以我刚开始用一个handsOn来改进,我正在学习netty,我是一个初学者。 我尝试了一个简单的客户端服务器与Netty聊天。 客户端和服务器正在初始化,我可以看到服务器能够获得用于建立连接的客户端管道,但是当客户端发送消息时,它没有进入ServerAdapterHandler的messageReceived部分。下面是我的源代