nio tcp之Socket系列通道 (四)

来源:互联网 发布:淘宝什么是千人千面 编辑:程序博客网 时间:2024/04/26 16:04

这一章比较重要,特别是selector,需要弄清楚这个。

package Demo4;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.Iterator;/** * 单线程只能连接一个客户端 * 线程池可连接多个客户端,开销非常大 * * nio 是可以使用单个线程连接多个客户端,开销小 * * @author Douglasli * */public class NioServer {//通道管理器private Selector selector;/** * 初始化一个ServerSocket通道 * @param port 端口号 * @throws IOException */public void initServer(int port) throws IOException{//获得一个ServerSocket通道ServerSocketChannel serverChannel = ServerSocketChannel.open();//设置通道为非阻塞(必须设置为false)serverChannel.configureBlocking(false);//将该通道对应的ServerSocket绑定到port端口serverChannel.socket().bind(new InetSocketAddress(port));//获得一个通道管理器this.selector = Selector.open();//将通道管理器和通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件serverChannel.register(selector, SelectionKey.OP_ACCEPT);}/** * 采用轮询的方式监听selector上是否有需要处理的时间 * @throws IOException selector.select()方法抛的异常 */public void listen() throws IOException{System.out.println("NIOServer start");while(true){//当注册的事件到达时,方法返回,否则,该方法一直阻塞//select()方法返回的int值表示有多少通道已经就绪,每次select()方法调用之间,只有一个通道就绪了,所以本案例中这个n只会等于1int n = selector.select();System.out.println(n);Iterator<?> it = this.selector.selectedKeys().iterator();while(it.hasNext()){SelectionKey key = (SelectionKey)it.next();it.remove();handler(key);}}} public void handler(SelectionKey key) throws IOException{//客户端 请求连接事件if(key.isAcceptable()){handlerAccept(key);}else if(key.isReadable()){handlerRead(key);}}//private void handlerAccept(SelectionKey key) throws IOException {ServerSocketChannel server = (ServerSocketChannel) key.channel();//获得和客户端连接的通道SocketChannel channel = server.accept();channel.configureBlocking(false);System.out.println("client link success!!!!");//在和客户端连接成功之后,为了可以接收到客户端的信息,需要给通道设置读的权限。channel.register(this.selector, SelectionKey.OP_READ);}//读取从客户端发来的消息,并且做出响应,private void handlerRead(SelectionKey key) {try {SocketChannel channel = (SocketChannel) key.channel();ByteBuffer buf = ByteBuffer.allocate(1024);int read = channel.read(buf);if(read>0){byte[] data = buf.array();String msg = new String(data).trim();System.out.println("server msg:"+ msg);//回写数据给客户端ByteBuffer out = ByteBuffer.wrap(msg.getBytes());channel.write(out);}else{System.out.println("client close,no msg accept in Server");key.cancel();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String[] args) throws IOException {NioServer server = new NioServer();server.initServer(8000);server.listen();}}

上面例子测试:

运行上述Demo,即是启动NIOServer服务器。

启动telnet客户端 :cmd 命令窗口 telnet 127.0.0.1 8000,会出现命令窗口什么都没有的情况(如左图),请接着按下CTRL+]快捷键即可(如右图)。


eclipse测试台结果:


原创粉丝点击