background image

writev 是系统调用,在 Java 里是用到 GatheringByteChannel.write(ByteBuffer[] srcs, int offset, 
int length)方法来做聚集写。这里可能还有一点值的提下,很多同学看 java nio 框架几乎都不
用这个

writev 调用,这是有原因的。主要是因为 Java 的 write 本身对 ByteBuffer 有做临时缓

存,而

writev 没有做缓存,导致测试来看 write 反而比 writev 更高效,因此通常会更推荐用

户将

head 和 body 放到同一个 Buffer 里来避免调用 writev。

下面我们将做个实际的代码测试来结束讨论。这个例子很简单,客户端发送一行数据到服务
器,服务器简单地将这行数据返回。客户端发送的时候可以选择分两次发,还是一次发送。
分两次发就是

write-write-read,一次发就是 write-read-write-read,可以看看两种形式下延迟

的差异。注意,在

windows 上测试下面的代码,客户端和服务器必须分在两台机器上,似乎

winsock 对 loopback 连接的处理不一样。

服务器源码:

package net.fnil.nagle;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8000));
System.out.println(

“Server startup at 8000″);

for (;;) {
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();

while (true) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
out.write((line + 

”\r\n”).getBytes());

}
catch (Exception e) {
break;
}