如何在不先从客户端接收数据的情况下获取客户端的端口和地址?

How do i get the port and address of client without receiving data from it first?

我正在制作一个简单的 UDP 聊天程序,我希望服务器能够发送给客户端而无需先从客户端接收数据。正常情况下,服务端收到客户端的数据后,会得到客户端的IP和端口,才能与之通信。

我的服务器代码:

package com.ageforce;

import java.io.*;
import java.net.*;
import java.util.Scanner;

public class ChatServer {
    DatagramSocket server;
    byte[] receivedData = new byte[1024];
    Scanner scanner = new Scanner(System.in);
    byte[] sentData;
    DatagramPacket dp2 = new DatagramPacket(receivedData, receivedData.length);

    public ChatServer() throws SocketException {
        server = new DatagramSocket(7000);
    }

    public static void main(String[] args) throws SocketException {
        ChatServer cs = new ChatServer();

        Thread receiveMessage = new Thread(() -> {
            while (true) {
                try {
                    cs.server.receive(cs.dp2);

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

                String storedData = new String(cs.dp2.getData());
                System.out.println(storedData);
            }
        });

        Thread sendMessage = new Thread(() -> {
            while (true) {
                String sentMessage = cs.scanner.nextLine();
                cs.sentData = sentMessage.getBytes();

                // This is the area of the code where the server gets IP and port of client from the received data. I'd like this to be changed.
                InetAddress getIP = cs.dp2.getAddress();
                int port = cs.dp2.getPort();

                DatagramPacket dp3 = new DatagramPacket(cs.sentData, cs.sentData.length, getIP, port);
                try {
                    cs.server.send(dp3);

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


        sendMessage.start();
        receiveMessage.start();
    }
}

这可以吗?非常感谢任何答复。

How do i get the port and address of client without receiving data from it first?

UDP 不提供这种可能性。它是一种无连接协议,因此服务器甚至不知道 个客户端,直到它收到来自客户端的消息。

你可以想象创建某种初步的应用程序级协议,客户端在向服务器发送任何聊天数据之前向服务器声明自己,但 UDP 本身没有任何东西,如果这是你想要的,那么您应该考虑改用 TCP,它确实具有在发送任何数据之前建立连接的内置概念。

为了向某物发送 UDP 消息,您需要知道要将其发送到的 IP 和端口号。如何?好吧,你告诉我。

您的协议现在的工作方式是 客户端 知道您的主机名(他们让他们的系统自动将其转换为 IP),并且端口号被硬编码在客户端应用程序。 服务器在收到呼叫时通过检查'sender'IP/port知道将数据发送回哪个IP和端口。

如果您不喜欢当前的协议,则需要想出一种不同的方式来回答这个问题。

即使你找到了方法,你也会发现这多半是没用的。绝大多数最终用户有意没有所谓的公共可路由 IP 地址。您无法通过设计联系到他们。在您当前的协议中,您发回的 IP/port 组合根本不是真正的发送计算机。就是一些路由器,比如他们家的路由器。该路由器看到 传出 UDP 数据包并记了一会儿:进入该端口的任何流量都应该转到这所房子里的那台计算机。

缺少完全疯狂的东西,例如 'hole punching'(Skype 使用了一段时间,不确定他们是否仍然使用,这是一个复杂的 hack,并不总是有效,肯定不是你想要的- 您可以在网络上搜索该术语),您在这里无能为力。最终用户系统不是服务器,无法像这样访问。

您的 运行-of-the-mill 聊天应用程序将始终让客户端 ping 服务器,然后尽可能长时间地保持连接打开。