我正在使用UDP客户端与我无法控制的服务器进行通信。与此服务器通信的部分要求是我必须向服务器提供一个UDP端口号[作为消息的一部分]以进行回复通信。
我的应用程序中有几个类需要一个DatagramSocket,代表对该服务器的不同请求,所以我创建了一个静态类:
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()类中,我抓住这个套接字连接并在整个应用程序中使用它:
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:已绑定
需要知道:
UDP服务器在我的机器上(localhost),但它是一个已编译的应用程序,因此我无法检查其代码。是的,它来自一个值得信赖的来源。
没有防火墙或网络问题,因为它是一台独立的计算机,所有东西都是敞开的。
在创建静态DatagramSocketGrabber类之前,我在所有消息类中创建了一个新的DatagramSocket,服务器能够成功接收我的消息。
然而,我创建静态类的原因是因为我没有收到任何回复,我确定这是因为我没有将我的套接字绑定到"固定"接收端口。为了做到这一点,并且能够在我的所有消息类中使用该绑定套接字,我想我需要创建一个DatagramSocket创建类,以便拥有一个可以传递的单个绑定套接字。
答案 0 :(得分:1)
我的猜测是,因为你没有共享抛出SocketException的代码,所以是以下之一。
1)你在程序中第二次调用DatagramSocketGrabber.getSocket();
,因此出现SocketException。
2)您留下了一些绑定到同一端口的代码(如new InetSocketAddress(15346);
)
尝试在代码中搜索套接字绑定(15346)并尝试查找程序中是否有其他DatagramSocketGrabber.getSocket();
调用。
同时,您可以将DatagramSocketGrabber更改为单例并将DatagramSocket保留为属性,这样您就可以随时调用单例而不是将套接字传递给所有方法。
答案 1 :(得分:0)
好的......我明白了。经过一天的谷歌搜索后,我在StackOverflow上发现了 this 。我所要做的只是从
更改DatagramSocketGrabberDatagramSocket newSocket = new DatagramSocket();
到
DatagramSocket newSocket = new DatagramSocket(null);
一切都按预期工作。解释如下:
为数据报套接字调用no-arg构造函数将导致它绑定到随机可用端口。一旦绑定,进一步尝试(重新)绑定将抛出套接字异常(带有您看到的错误)。要“延迟”绑定,您需要在未绑定状态下创建数据报套接字(通过在构造函数中传递null),然后再调用bind。
感谢Perception他/她的回答!