用Java DatagramSocket发送数据包到255.255.255.255失败。

15
我正在使用Java编写网络程序,我想发送一些数据包到255.255.255.255,但是无法成功发送,即使我将它们发送到ifconfig命令输出中的广播地址192.168.1.255也是如此。但当我将它们发送到我的朋友IP时,它可以正常工作。
这是我的程序代码:
public class StackOverFlow {
    public static void main(String[] args) {
        Network net= new Network();

        Scanner input= new Scanner(System.in);
        while(input.hasNext())
          net.sendMessage(input.nextLine());
    }
}

我已经使用DatagramSocket和DatagramPacket来实现网络传输,这是我的网络实现:

class Network {
DatagramSocket socket;

public Network() {
    try {
        socket = new DatagramSocket(8027);
        socket.connect(InetAddress.getByName("255.255.255.255"), 8027);
    } catch (Exception e) {
        System.err.println("Connection failed. " + e.getMessage());
    }
    listen();
}

public void listen() {
    new Thread() {
        public void run() {
            while (true) {
                try {
                    byte[] buf = new byte[1000];
                    DatagramPacket packet = new DatagramPacket(buf,
                            buf.length);
                    socket.receive(packet);
                    String message = new String(buf);
                    System.out.println("Recieved: " + message);
                    if (message.equals("end"))
                        return;
                } catch (Exception e) {
                    System.err.println(e.getMessage());
                }
            }
        }
    }.start();
}

public void sendMessage(String message){
    byte[] buf= message.getBytes();

    DatagramPacket packet= new DatagramPacket(buf, buf.length);
    try{
        socket.send(packet);
    }catch(Exception e){
        System.err.println("Sending failed. " + e.getMessage());
    }
}

没有任何异常被抛出。
我在一个临时网络中。
我正在使用MAC OS X 10.6,而我的同伴正在使用kubuntu 11.04。 以下是ifconfig的输出:

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet6 ::1 prefixlen 128 
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 
inet 127.0.0.1 netmask 0xff000000 
gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
stf0: flags=0<> mtu 1280

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet6 fe80::21f:f3ff:fed5:4779%en0 prefixlen 64 scopeid 0x4 
inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255
ether 00:1f:f3:d5:47:79 
media: autoselect (100baseTX <full-duplex>) status: active
supported media: autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 10baseT/UTP     <full-duplex,hw-loopback> 10baseT/UTP <full-duplex,flow-control> 100baseTX <half-    duplex> 100baseTX <full-duplex> 100baseTX <full-duplex,hw-loopback> 100baseTX <full-duplex,flow-control> 1000baseT <full-duplex> 1000baseT <full-duplex,hw-loopback> 1000baseT <full-duplex,flow-control> none

en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet6 fe80::21d:4fff:feff:2b4d%en1 prefixlen 64 scopeid 0x5 
inet 213.233.170.97 netmask 0xfffffc00 broadcast 213.233.171.255
ether 00:1d:4f:ff:2b:4d 
media: autoselect status: active
supported media: autoselect

fw0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 2030
lladdr 00:21:e9:ff:fe:bc:79:b2 
media: autoselect <full-duplex> status: inactive
supported media: autoselect <full-duplex>

en2: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 00:1f:f3:b6:2c:be 
media: autoselect status: inactive
supported media: none autoselect 10baseT/UTP <half-duplex>

vmnet1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.149.1 netmask 0xffffff00 broadcast 192.168.149.255
ether 00:50:56:c0:00:01 

vmnet8: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
inet 192.168.73.1 netmask 0xffffff00 broadcast 192.168.73.255
ether 00:50:56:c0:00:08 

en0是我用来连接我的伙伴的设备。

请简单明了一点,我是新手 :)

提前致谢。


请展示 ifconfig 的输出! - Volker Stolz
4个回答

11

使用广播时需要启用它

socket.setBroadcast(true);

另外一件事是,如果两台计算机位于不同的网络中,您必须确保路由器配置正确。广播通常默认情况下不能路由。此外,如果您的路由器具有无线接口和有线接口,如果未启用广播,则这些广播也可能无法正常工作(某些硬件默认转发这两个接口之间的广播)。


我在 socket.connect(...) 后面添加了 socket.setBroadcast(true)。但它仍然无法工作。问题出在哪里? - Pro.Hessam
谢谢,但是没有路由器。这是一个点对点的网络。但它不起作用。 在网络中广播的常规方式是什么? - Pro.Hessam
通常的方法是设置一个多播服务器,并让客户端注册为多播组的多播客户端。 - fyr

6
不要将您的DatagramSocket连接到广播地址,而是构造DatagramPacket以针对它进行目标设置,即:
DatagramPacket dp = new DatagramPacket(byteArray, byteArray.length, InetAddress.getByName("255.255.255.255"), yourPortNumber);

像魔术一样,您已经发送了广播。然后,在另一端捕获它,只需在该端口上进行侦听:

DatagramSocket dsock = new DatagramSocket(samePortUsedAbove);
DatagramPacket dp = new DatagramPacket(byteArray, byteArray.length);
dsock.receive(dp);

3
192.168.1.255 
  • 请检查您网络中的子网掩码。可能您发送信息和接收信息的机器不在同一个网络中。
  • 请确认接收信息的机器在您的网络中存在。
  • 如果您的机器之间有路由器,我认为信息将无法传输。

@Karnahire,此时此刻,我正在向自己发送数据包(通过向“192.168.1.255”发送数据包)。但是我无法接收它们。但是当我向“localhost”发送数据包时,它可以正常工作。 - Pro.Hessam
IPең°еқҖ192.168.1.255еңЁWindowsе’ҢMacдёӯж— жі•дҪҝз”Ёе№ҝж’ӯеҠҹиғҪгҖӮжҲ‘дёҚзҹҘйҒ“дёәд»Җд№Ҳпјҹ - Kamahire

1

真的吗?可是怎么做呢?我应该有一个DatagramSocket来发送,另一个DatagramSocket来接收吗?而且两个都在同一个端口上?我觉得这是不可能的。(我觉得操作系统不会允许我们使用相同端口的两个套接字) - Pro.Hessam
@Pro.Hessam,发送者不必使用特定的端口,任何端口都可以。 - Volker Stolz
你的意思是我发送数据包到8030端口,然后从8027端口接收它们,是这样吗? 我创建了一个连接到255.255.255.255的DatagramSocket和一个连接到本地主机的DatagramSocket,其中一个使用8030端口,另一个使用8027端口。但是它没有起作用。问题出在哪里? - Pro.Hessam
@Pro.Hessam:客户端在8030上监听。发送方 bind 到8027,并发送到8030。那应该可以工作。这将是基本测试。如果源端口和目标端口相同,它甚至可能起作用,但重要的是不要在255.255.255.255上进行listen,而是在实际的本地IP上进行。因此,您将需要使用两个不同的套接字。 - Volker Stolz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接