需要帮助让我的 Java UDP 客户端应用程序正常工作

Need assistance getting my Java UDP client application working

我正在使用 UDP 客户端与我无法控制的服务器进行通信。与此服务器通信的部分要求是我必须向服务器提供 UDP 端口号 [作为消息的一部分] 以进行回复通信。

我的应用程序中有几个 classes,它们需要一个 DatagramSocket,代表对该服务器的不同请求,所以我创建了一个静态 class:

package mypackage;

import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;

public class DatagramSocketGrabber {

    public DatagramSocketGrabber(){}

    public static DatagramSocket getSocket() throws SocketException {
        DatagramSocket newSocket = new DatagramSocket();
        InetSocketAddress newSocketAddress = new InetSocketAddress(15346);
        newSocket.bind(newSocketAddress);
        return newSocket;
    }
}

在我的 main() class 中,我正在获取此套接字连接并在我的整个应用程序中使用它:

package mypackage;

import java.net.DatagramSocket;
import java.net.SocketException;

public class MyApp {
    public static void main(String[] args){
        DatagramSocket mySocket = null;

        try {
            mySocket = DatagramSocketGrabber.getSocket();
        } catch(SocketException se){
            System.out.println(se);
        }

        DSClass01 class01 = new DSClass01(mySocket);
        DSClass02 class02 = new DSClass02(mySocket);
        DSClass03 class03 = new DSClass03(mySocket);

        mySocket.close();
    }
}

但是,每当我 运行 我的应用程序时,我总是收到错误消息:

java.net.SocketException: already bound

需要知道

UDP 服务器在我的机器 (localhost) 上,但它是一个已编译的应用程序,所以我无法检查它的代码。是的,来源可靠。

没有防火墙或网络问题,因为它是一台独立的计算机,所有内容都是开放的。

在创建静态 DatagramSocketGrabber class 之前,我在所有消息 classes 中创建了一个新的 DatagramSocket,并且服务器能够成功接收我的消息。

但是,我创建静态 class 的原因是因为我没有收到任何回复,我确定这是因为我没有将我的套接字绑定到 "fixed" 接收端口。为了做到这一点,并能够在我的所有消息 classes 中使用该绑定套接字,我想我需要创建一个 DatagramSocket 创建 class 来拥有一个我可以的绑定套接字绕过去。

我的猜测是,由于您不共享抛出 SocketException 的代码是以下代码之一。

1) 您在程序中第二次调用 DatagramSocketGrabber.getSocket();,因此出现 SocketException。

2) 您留下了一些绑定到同一端口的代码(如 new InetSocketAddress(15346);

尝试在您的代码中搜索套接字绑定 (15346),并尝试查找您的程序中是否有任何其他 DatagramSocketGrabber.getSocket(); 调用。

同时,您可以将 DatagramSocketGrabber 更改为单例并将 DatagramSocket 保留为属性,这样您就可以始终调用单例而不是将套接字传递给所有方法。

好的...我明白了。经过一天的谷歌搜索,我在 Whosebug 上找到了 this post。我所要做的就是将 DatagramSocketGrabber 从

DatagramSocket newSocket = new DatagramSocket();

DatagramSocket newSocket = new DatagramSocket(null);

一切都按预期进行。解释是这样的:

Calling the no-arg constructor for a datagram socket will cause it to bind to a random, available port. Once bound, further attempts to (re)bind will throw a socket exception (with the error you were seeing). To 'defer' binding, you instead create the datagram socket in an unbound state (by passing a null in the constructor), then calling bind later on.

感谢 Perception 的 his/her 回答!