收到空的UDP多播

时间:2018-11-24 13:20:25

标签: java udp nio multicast

我正在以非阻塞模式使用连接的DatagramChannel来接收UDP多播。我发现DatagramChannel.read(ByteBuffer)每当我的程序收到空的UDP多播消息时都返回 -1 。但是API文档说:“ 读取的字节数,可能为零,或者如果通道已到达流末尾,则为-1 ”。

我希望流结束是无法再使用该通道的条件-就像封闭的TCP连接一样,但是完全有可能继续使用DatagramChannel用于 -1 之后接收。

可以安全地假设即使read(ByteBuffer)返回 -1 之后,仍然可以继续使用DatagramChannel吗?

当接收到一个空的UDP消息时,有一个返回值指示流结束的返回值对有点有点奇怪吗?如果返回值为 0 会更合适吗?

这是我的测试程序,首先是多播发射机:

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class LocalServer {
    final static int PORT = 7001;

    final static String MCAST_ADDRESS = "233.2.3.3";
    final static String INTERFACE_ADDRESS = "127.0.0.1";

    public static void main(String[] args) throws IOException {

        NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(INTERFACE_ADDRESS));
        System.out.println("ChannelServer: ni=" + ni.getDisplayName());
        DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET).setOption(StandardSocketOptions.SO_REUSEADDR, true).bind(
            new InetSocketAddress(PORT)).setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
        InetAddress group = InetAddress.getByName(MCAST_ADDRESS);

        SocketAddress dst = new InetSocketAddress(group, PORT);
        int i = 0;
        while (true) {
            System.out.println("Transmitting #" + i);
            ByteBuffer asterixBuf = ByteBuffer.wrap(
                ("line " + i + "123456789012345678901234567890123456789012345678901234567890").getBytes());
            dc.send(asterixBuf, dst);
            i++;

            // Randomly transmit an empty UDP datagram and then sleep.
            if (Math.random() > 0.50d) {
                System.out.println("Transmitting an empty buffer");
                ByteBuffer emptyBuf = ByteBuffer.allocate(0);
                dc.send(emptyBuf, dst);
                try {
                    Thread.sleep(300);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

然后是多播接收器:

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.StandardProtocolFamily;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;

public class LocalClient {
    final static int PORT = LocalServer.PORT;

    final static String MCAST_ADDRESS = LocalServer.MCAST_ADDRESS;
    final static String CONNECT_HOST = LocalServer.INTERFACE_ADDRESS;
    final static String INTERFACE_ADDRESS = CONNECT_HOST;

    public static void main(String[] args) throws IOException {
        NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName(INTERFACE_ADDRESS));
        System.out.println("ChannelClient: ni=" + ni.getDisplayName());
        DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET).setOption(StandardSocketOptions.SO_REUSEADDR, true).bind(
            new InetSocketAddress(PORT)).setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);
        InetAddress group = InetAddress.getByName(MCAST_ADDRESS);
        MembershipKey key = dc.join(group, ni);
        dc.configureBlocking(false);
        InetSocketAddress foreignInetAddress = new InetSocketAddress(InetAddress.getByName(CONNECT_HOST), 0);
        dc.connect(foreignInetAddress);

        ByteBuffer receiveBuffer = ByteBuffer.allocate(64 * 1024);
        while (true) {
            dc.receive(receiveBuffer);
            int bytesRead = dc.read(receiveBuffer);
            if (bytesRead == -1) {
                System.out.println("bytesRead=" + bytesRead);
            }
            else if (bytesRead > 0) {
                receiveBuffer.flip();
                System.out.println();
                while (receiveBuffer.hasRemaining())
                    System.out.print((char) receiveBuffer.get());
                System.out.println();
                receiveBuffer.clear();
                try {
                    Thread.sleep(100);
                }
                catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

0 个答案:

没有答案