Java SocketChannel:为什么wrap-flip-write不起作用但是wrap-write呢?

时间:2013-10-01 13:27:13

标签: java nio bytebuffer socketchannel

假设我们有一个Java SocketChannel连接到正在等待传入数据的服务器:

SocketChannel server = SocketChannel.open();
server.connect(new InetSocketAddress(ip, port));

我们发送请求如下:

byte[] request = "This is a request for server!".getBytes();
ByteBuffer buffer = ByteBuffer.wrap(request);
buffer.flip();
int write = 0;
while (buffer.hasRemaining())
    write += server.write(buffer);
System.out.println(write);

上面的代码返回0,这意味着它不会向通道写入任何字节!

但如果删除buffer.flip()行,它将正常工作并发送数据:

byte[] request = "This is a request for server!".getBytes();
ByteBuffer buffer = ByteBuffer.wrap(request);
int write = 0;
while (buffer.hasRemaining())
    write += server.write(buffer);
System.out.println(write);

为什么会这样?!

2 个答案:

答案 0 :(得分:3)

我自己想出了这个问题,所以我在StackOverflow上写这篇文章来分享信息,对于遇到同样问题的其他人也很有用。

根据ByteBuffer.wrap()的{​​{3}}:

  

新缓冲区的容量和限制将为array.length,其位置将为零,其标记将不确定。

Buffer.flip()的{​​{3}}说:

  

翻转此缓冲区。限制设置为当前位置,然后位置设置为零。如果定义了标记,则将其丢弃。

现在答案很明确:wrap()将缓冲区的位置设置为零,flip()将缓冲区的限制设置为当前位置(为零),write(buffer)将从位置限制哪些都是0,因此它什么都不写!

答案 1 :(得分:0)

wrap()提供已经翻转的缓冲区。再次翻转它基本上会从write()或get()的角度清空它。