java - 为什么不同的 DatagramSocket 构造函数的行为如此不同? (绑定(bind)异常)

标签 java sockets exception bind datagram

我正在构建一个程序,通过 DatagramSocket 和 DatagramPacket 将 LAN 中的每台计算机连接到我的计算机(换句话说,我将成为服务器,其他计算机将成为客户端)。我做了一些研究并阅读了文档,并了解了它是如何工作的,而且我实际上已经能够通过网络发送和接收数据。我在客户端类中的数据发送方法有两个选项,我认为它们是等效的,但似乎不是。 第一个(Client1):

DatagramSocket socket = null;
DatagramPacket packet = null;

try
{
     byte[] data= "test".getBytes();
     packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
     socket = new DatagramSocket();
     socket.send(packet);
 }
 catch (Exception ex)
 {
     ...
 }

第二个(Client2):

DatagramSocket socket = null;
DatagramPacket packet = null;

try
{
     byte[] data= "test".getBytes();
     packet = new DatagramPacket(data, data.length);
     socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));
     socket.send(packet);
 }
 catch (Exception ex)
 {
     ...
 }

这两个选项是在我测试向自己的 PC 发送数据或从自己的 PC 发送数据时出现的。我的IP地址是192.168.0.26。对于第一个我没有任何问题,但第二个抛出了两种异常。我可以验证 Client1 是否可以同时在计算机中运行下一个代码

(服务器)

byte data[] = null;
try
{
    data= new byte[1000];
    socket = new DatagramSocket(325);
    packet = new DatagramPacket(datos, datos.length);
    socket.receive(packet);
    System.out.println(datos);
}
catch (Exception ex)
{
    ...
}

如果我先运行 Server,然后运行 ​​Client1 选项,它实际上会收到数据。当我先运行 Client1 然后运行 ​​Server 时,显然没有得到任何数据,但也没有得到任何异常。真正的问题(也是实际的问题,抱歉有这么多可能无用的信息)是 Client2。如果这是在服务器之前运行的,我会得到 NullPointerException:

java.lang.NullPointerException: null address || null buffer
at java.net.DualStackPlainDatagramSocketImpl.send(DualStackPlainDatagramSocketImpl.java:115)
at java.net.DatagramSocket.send(DatagramSocket.java:676)

调用方法 send() 时生成。我知道也许我应该忽略这一点;即使我对套接字有点新手,如果你知道没有人会收到数据,那么发送数据似乎是错误的。另一方面,当 Server 先运行然后 Client2 运行时,我得到 BindException:

java.net.BindException: Address already in use: Cannot bind
at java.net.DualStackPlainDatagramSocketImpl.socketBind(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.bind0(DualStackPlainDatagramSocketImpl.java:65)
at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:95)
at java.net.DatagramSocket.bind(DatagramSocket.java:376)
at java.net.DatagramSocket.<init>(DatagramSocket.java:231)
at java.net.DatagramSocket.<init>(DatagramSocket.java:284)

来自套接字初始化时的行。 由于 Client1 可以工作,我将使用它;但我真的很想知道为什么它可以工作但 Client2 却不能。我在另一个论坛上读到了有关 BindException 的信息,我知道这是当您尝试使用一个已在使用的端口时引起的,但从这个意义上讲,Client1 也应该失败。有人可以解释一下 Client1 和 Client2 之间的区别吗?

最佳答案

您正在绑定(bind)到同一端口,如果您在同一机器/地址上运行它,则需要绑定(bind)到不同的端口。

就像在服务器上一样:

socket = new DatagramSocket(325);    //server binds its UDP/IP socket to port 325

在客户端2上:

socket = new DatagramSocket(325, InetAddress.getByName("192.168.0.26"));

您正在绑定(bind)到“服务器”正在使用的同一台计算机/地址上的同一端口

在客户端 1 上:

packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.0.26"), 325);
//you are specifying the destination address and port the packet should be sent.
socket = new DatagramSocket();
//but in the DatagramSocket contructor you don't pass any address or port to bind to, so it will use an available port, not 325 as it is in use by the server.

正如您所说,您是网络通信新手,请记住这是 UDP/IP 套接字,还有 TCP/IP 和其他套接字。 UDP/IP 不是面向连接的规范,并且不保证数据包的传送。

关于java - 为什么不同的 DatagramSocket 构造函数的行为如此不同? (绑定(bind)异常),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18709234/

相关文章:

java - 获取特定字符串值之前的单词

linux - 为什么非阻塞 TCP connect() 在 Linux 上偶尔会这么慢?

java - 由其他异常引起的异常

java - 如何使这个单元测试独立?

java - 在您的环境中找不到 Jenkins 和 maven JAVA_HOME

c# - 如何正确清理 TcpListener,以避免 "Address already in use"错误?

c - c 中令人恼火的 select() 行为

ios - MKMapView addAnnotations 崩溃

java - BeanCreationException NoSuchBeanDefinitionException 在为以下 Spring 代码启动 Google App Server 时

java - Selenium Webdriver - Java - 验证部分文本显示末尾有三个点