哎,昨晚又加班。可是还是很准时的醒了....上午不用去公司,正好继续补全我的博客:)
大家都知道自从jdk5开始,java中多了java.nio和java.util.concurent包,这两个包
可谓威力无穷啊,像tomcat最新版本(用了concurrent包),mina等纷纷在此基础上进行了
更新(mina更是直接就通过java.nio来实现的)。
其实nio说起来很简单。
java通信的基础是socket.和serversocket 在此基础上封装一下,就是socketchannel和serversocketchannel,
封装成channel的最大好处就是可以实现non-blocking的通信。然后再加入了一个多路轮询机制,通过观察者模式
使得通过单线程就可以同时管理多个channel. 明白了这些之后,放出我的例子来。分别使用socket,channel,selector
实现了java的通信。
坦白讲,在写这些代码之前我对channel,selector等的概念还是比较模糊的。
写完之后清晰多了:实际上就是对java socket通讯的一种优化手段。
Server:
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;
public class TestChannel {
public static void main(String args[]) throws IOException{
TestChannel tt=new TestChannel();
//tt.initServerChannel(992);
tt.initSelector(992);
}
//最初的java socket实现方式,直接通过serversocket和socket通信
public void initServerSocket(int port) throws IOException{
ServerSocketChannel ssc=ServerSocketChannel.open();
//ssc.configureBlocking(false);
ServerSocket ss=new ServerSocket(port);
while(true){
Socket socket=ss.accept();
System.out.println("socket accepted");
byte[] buf=new byte[1024];
try{
socket.getInputStream().read(buf);
}
catch(Exception ex){
socket.close();
}
System.out.println(new String(buf));
}
}
//通过Channel实现的non-blocking通信方式
public void initServerChannel(int port) throws IOException{
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss=ssc.socket();
ss.bind(new InetSocketAddress(port));
while(true){
SocketChannel sc=ssc.accept();
if(sc!=null){
Socket socket=sc.socket();
System.out.println("socket accepted");
byte[] buf=new byte[1024];
try{
socket.getInputStream().read(buf);
}
catch(Exception ex){
socket.close();
}
System.out.println(new String(buf));
}
}
}
//通过selector和channel进行multiplexed通信,像mina就是通过这种方式实现的
public void initSelector(int port) throws IOException{
Selector selector=Selector.open();
//register server channel
ServerSocketChannel ssc=ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss=ssc.socket();
ss.bind(new InetSocketAddress(port));
ssc.register(selector, SelectionKey.OP_ACCEPT);
while(true){
int interestNo=selector.select();
if(interestNo==0)
continue;
Set<SelectionKey> keys=selector.selectedKeys();
for(SelectionKey key:keys){
//接受Socket连接请求
if(key.isAcceptable()){
SocketChannel sc=ssc.accept();
try{
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
}
catch(Exception ex){
sc.close();
}
System.out.println("connection accepted");
keys.remove(key);
}
else if(key.isReadable()){
SocketChannel sc=(SocketChannel)key.channel();
ByteBuffer bbuf=ByteBuffer.allocate(1024);
try{
sc.read(bbuf);
}
catch(Exception ex){
sc.close();
}
System.out.println(new String(bbuf.array()));
keys.remove(key);
}
else
keys.remove(key);
continue;
}
}
}
}
client:
public class TestChannelClient {
public static void main(String args[]) throws UnknownHostException, IOException{
Socket sc=new Socket("127.0.0.1",992);
OutputStream out=sc.getOutputStream();
out.write("hello".getBytes());
out.flush();
}
}