编写过socket的程序员都知道ServerSocket的accept()是阻塞的。所谓阻塞,在代码中的体现就是该语句不会返回,直到有新连接到来。但是阻塞模式会影响到服务器的可伸缩性,在JDK1.4中增加的nio包对io进行了扩充,提供了非阻塞的模式。
下面模拟一个服务器和客户端交互的例子。服务器端采用非阻塞的socket:
package org.snake.channels;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
public class NonBlockingServer {
public static final String GREETING = "你好,再见!\r\n";
public static void main(String[] args) throws Exception {
ByteBuffer buffer = ByteBuffer.wrap(GREETING.getBytes());
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(54321));
ssc.configureBlocking(false); // 非阻塞模式
while (true) {
System.out.println("等待连接");
SocketChannel sc = ssc.accept();
if (sc == null) {
// 没有连接,休息片刻
TimeUnit.SECONDS.sleep(2);
} else {
System.out.printf("新连接来自:%s", sc.socket()
.getRemoteSocketAddress());
buffer.rewind();
sc.write(buffer);
sc.close();
}
}
}
}
客户端:
Telnet localhost 54321
服务端输出:
等待连接
等待连接
等待连接
等待连接
等待连接
新连接来自:/0:0:0:0:0:0:0:1:24079等待连接
等待连接
等待连接
等待连接
等待连接
等待连接
你好,再见!
遗失对主机的连接。