转载自:http://aaries.iteye.com/blog/1139440
1.服务器端while(true) 一直等待client端来连接。
基本步骤为:
- ServerSocketChannel server = ServerSocketChannel.open();
- server.configureBlocking(false);
- server.socket().bind(new InetSocketAddress(5200));
- Selector select = Selector.open();
- server.register(select, SelectionKey.OP_ACCEPT);
声明一个等待客户端的服务器。
- select.select();
- Set readkeys = select.selectedKeys();
- Iterator iterator = readkeys.iterator();
- while (iterator.hasNext()) {
- SelectionKey key = (SelectionKey) iterator.next();
- if (key.isAcceptable()) {
- SocketChannel client = ((ServerSocketChannel) key.channel()).accept();
- System.out.println("Accept connection from: " + client);
- client.configureBlocking(false);
- client.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(1024));
- }
- if (key.isReadable()) {
- // 获得与客户端通信的信道
- SocketChannel clientChannel = (SocketChannel) key.channel();
- // 得到并清空缓冲区
- ByteBuffer buffer = (ByteBuffer) key.attachment();
- buffer.clear();
- // 读取信息获得读取的字节数
- long bytesRead = clientChannel.read(buffer);
- if (bytesRead == -1) {
- // 没有读取到内容的情况
- clientChannel.close();
- } else {
- // 将缓冲区准备为数据传出状态
- buffer.flip();
- // 将字节转化为为UTF-16的字符串
- String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString();
- // 控制台打印出来
- System.out.println("接收到来自" + clientChannel.socket().getRemoteSocketAddress() + "的信息:" + receivedString);
- // 准备发送的文本
- String sendString = "你好,客户端. @" + new Date().toString() + ",已经收到你的信息" + receivedString;
- buffer = ByteBuffer.wrap(sendString.getBytes("UTF-16"));
- clientChannel.write(buffer);
- // 设置为下一次读取或是写入做准备
- key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
- }
- }
- if (key.isWritable())
- {
- SocketChannel sc = (SocketChannel) key.channel();
- ByteBuffer writeBuffer=ByteBuffer.wrap("我的程序员之道".getBytes("UTF-16"));
- sc.write(writeBuffer);
- }
- key.channel().close();
- }
遍历键集,然后判断键的可读可写等做不同的操作
客户端建立一个线程,等待服务器端的回应:
1.建立基本的SocketChannel
- SocketChannel sc = SocketChannel.open(new InetSocketAddress("172.16.22.11", 5200));
- //打开一个SocketChannel并连接到服务器
- sc.configureBlocking(false);
- Selector selector = Selector.open();
- sc.register(selector, SelectionKey.OP_READ);
在实现Runable的run方法里遍历键集,判断做不同的操作:
- while (selector.select() > 0) {
- // 遍历每个有可用IO操作Channel对应的SelectionKey
- Iterator it = selector.selectedKeys().iterator();
- while (it.hasNext()) {
- SelectionKey sk = (SelectionKey) it.next();
- it.remove();
- // 如果该SelectionKey对应的Channel中有可读的数据
- if (sk.isReadable()) {
- // 使用NIO读取Channel中的数据
- SocketChannel socketChannel = (SocketChannel) sk.channel();
- ByteBuffer buffer = ByteBuffer.allocate(1024);
- socketChannel.read(buffer);
- buffer.flip();
- // 将字节转化为为UTF-16的字符串
- String receivedString = Charset.forName("UTF-16").newDecoder().decode(buffer).toString();
- // 控制台打印出来
- System.out.println("接收到来自服务器" + socketChannel.socket().getRemoteSocketAddress() + "的信息:" + receivedString);
- // 为下一次读取作准备
- // sk.interestOps(SelectionKey.OP_READ);//将键设为可读
- }
- if (sk.isWritable()) {
- SocketChannel socketChannel = (SocketChannel) sk.channel();
- ByteBuffer writeBuffer = ByteBuffer.wrap("我的程序员之道".getBytes("UTF-16"));
- socketChannel.write(writeBuffer);
- }
- // 删除正在处理的SelectionKey
- selector.selectedKeys().remove(sk);
- }
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }