DatagramChannel#read(ByteBuffer) は空データパケットを読めない

データをDatagramChannelで送る

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class Hoge1 {
    public static void main(String[] args) throws Exception {
        final DatagramChannel channel = DatagramChannel.open();
        InetSocketAddress address = new InetSocketAddress(12345);
        channel.bind(address).connect(address);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                ByteBuffer bb = ByteBuffer.allocate(10);
                try {
                    int read = channel.read(bb);
                    System.out.println("Read:" + read + ", " + bb);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        channel.write(ByteBuffer.allocate(1));
        t.join(3000);
        System.out.println("Close.");
        channel.close();
    }
}

結果は以下のとおり. 1バイト読めている.

Read:1, java.nio.HeapByteBuffer[pos=1 lim=10 cap=10]
Close.

0バイトのデータを送る

送るパケットを0バイトにしてみる.

23c23
<         channel.write(ByteBuffer.allocate(1));
---
>         channel.write(ByteBuffer.allocate(0));

すると結果は以下のようになり、パケットが読めていない.

Close.
java.nio.channels.AsynchronousCloseException
    at java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:205)
    at sun.nio.ch.DatagramChannelImpl.read(DatagramChannelImpl.java:565)
    at Hoge0$1.run(Hoge0.java:16)
    at java.lang.Thread.run(Thread.java:724)

connect() しない場合は0バイトでも読める

send()/receive() を使えば0バイトデータも読める.

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class HogeNonConnected {
    public static void main(String[] args) throws Exception {
        final DatagramChannel channel = DatagramChannel.open();
        InetSocketAddress address = new InetSocketAddress(12345);
        channel.bind(address);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                ByteBuffer bb = ByteBuffer.allocate(10);
                try {
                    SocketAddress remote = channel.receive(bb);
                    System.out.println("Read:" + remote + ", " + bb);
                } catch (Exception e) {
                    e.printStackTrace();

                }
            }
        });
        t.start();
        channel.send(ByteBuffer.allocate(0), address);
        t.join(3000);
        System.out.println("Close.");
        channel.close();
    }
}

結果

Read:/0:0:0:0:0:0:0:1:12345, java.nio.HeapByteBuffer[pos=0 lim=10 cap=10]
Close.

ReadableByteChannelの仕様上仕方ないのかしら. 生UDPで空パケットなんて送らないからさしあたり問題ないけど…