在Windows上使用Sun Java VM 1.5或1.6,我连接一个非阻塞套接字.然后我填写一条ByteBuffer
消息输出,并尝试进入write()
SocketChannel.
如果要写入的数量大于套接字TCP输出缓冲区中的空间量,我希望写入只能部分完成(这是我所期望的直观,这也是我对文档的理解),但那不是什么发生.该write()
总似乎返回报告写全款,即使是几兆字节(套接字的SO_SNDBUF为8KB,多少,比我的多兆字节输出消息少得多).
这里的问题是我无法测试处理部分写入输出的情况的代码(注册WRITE
选择器的兴趣集并执行select()
等待直到写入其余部分),因为这种情况似乎永远不会发生.我不明白的是什么?
我设法重现了一个可能类似于你的情况.我认为,具有讽刺意味的是,您的收件人比您编写数据的速度更快.
import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class MyServer { public static void main(String[] args) throws Exception { final ServerSocket ss = new ServerSocket(12345); final Socket cs = ss.accept(); System.out.println("Accepted connection"); final InputStream in = cs.getInputStream(); final byte[] tmp = new byte[64 * 1024]; while (in.read(tmp) != -1); Thread.sleep(100000); } } import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class MyNioClient { public static void main(String[] args) throws Exception { final SocketChannel s = SocketChannel.open(); s.configureBlocking(false); s.connect(new InetSocketAddress("localhost", 12345)); s.finishConnect(); final ByteBuffer buf = ByteBuffer.allocate(128 * 1024); for (int i = 0; i < 10; i++) { System.out.println("to write: " + buf.remaining() + ", written: " + s.write(buf)); buf.position(0); } Thread.sleep(100000); } }
如果您运行上述服务器,然后让上面的客户端尝试写入10个128 kB的数据块,您将看到每个写操作都会写入整个缓冲区而不会阻塞.但是,如果您修改上述服务器而不是从连接中读取任何内容,您将看到只有客户端上的第一个写操作将写入128 kB,而所有后续写入将返回0
.
服务器从连接读取时的输出:
to write: 131072, written: 131072 to write: 131072, written: 131072 to write: 131072, written: 131072 ...
服务器未从连接读取时的输出:
to write: 131072, written: 131072 to write: 131072, written: 0 to write: 131072, written: 0 ...