limit, mark,
? ? ? ? ? ? ? ? ? ? 而readBuffer.array()会返回整个缓冲区的内容。
? ? ? ? ? ? ? ? ? ? decode方法只取readBuffer的position到limit数据。
? ? ? ? ? ? ? ? ? ? 例如,上一次读取到缓冲区的是"where", clear后position为0,limit为 1024,
? ? ? ? ? ? ? ? ? ? 再次读取“bye"到缓冲区后,position为3,limit不变,
? ? ? ? ? ? ? ? ? ? flip后position为0,limit为3,前三个字符被覆盖了,但"re"还存在缓冲区中,
? ? ? ? ? ? ? ? ? ? 所以 new String(readBuffer.array()) 返回 "byere",
? ? ? ? ? ? ? ? ? ? 而decode(readBuffer)返回"bye"。? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? */
? ? ? ? ? ? ? ? ? ? CharBuffer charBuffer = CharsetHelper.decode(readBuffer);
? ? ? ? ? ? ? ? ? ? String question = charBuffer.toString();
? ? ? ? ? ? ? ? ? ? String answer = getAnswer(question);
? ? ? ? ? ? ? ? ? ? channel.write(CharsetHelper.encode(CharBuffer.wrap(answer)));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? //这里关闭channel,因为客户端已经关闭channel或者异常了
? ? ? ? ? ? ? ? ? ? channel.close();? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? catch(Throwable t){
? ? ? ? ? ? t.printStackTrace();
? ? ? ? ? ? if(channel != null){
? ? ? ? ? ? ? ? channel.close();
? ? ? ? ? ? }
? ? ? ? }? ? ?
? ? }
? ?
? ? private String getAnswer(String question){
? ? ? ? String answer = null;
? ? ? ?
? ? ? ? switch(question){
? ? ? ? case "who":
? ? ? ? ? ? answer = "我是小娜\n";
? ? ? ? ? ? break;
? ? ? ? case "what":
? ? ? ? ? ? answer = "我是来帮你解闷的\n";
? ? ? ? ? ? break;
? ? ? ? case "where":
? ? ? ? ? ? answer = "我来自外太空\n";
? ? ? ? ? ? break;
? ? ? ? case "hi":
? ? ? ? ? ? answer = "hello\n";
? ? ? ? ? ? break;
? ? ? ? case "bye":
? ? ? ? ? ? answer = "88\n";
? ? ? ? ? ? break;
? ? ? ? default:
? ? ? ? ? ? ? ? answer = "请输入 who, 或者what, 或者where";
? ? ? ? }
? ? ? ?
? ? ? ? return answer;
? ? }
}
客户端代码:
package com.stevex.app.nio;
?
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
?
?
public class Client implements Runnable{
? ? private BlockingQueue words;
? ? private Random random;
? ?
? ? public static void main(String[] args) {? ? ?
? ? ? ? //种多个线程发起Socket客户端连接请求
? ? ? ? for(int i=0; i<10; i++){
? ? ? ? ? ? Client c = new Client();
? ? ? ? ? ? c.init();
? ? ? ? ? ? new Thread(c).start();
? ? ? ? }? ? ?
? ? }
?
? ? @Override
? ? public void run() {? ? ?
? ? ? ? SocketChannel channel = null;
? ? ? ? Selector selector = null;
? ? ? ? try {
? ? ? ? ? ? channel = SocketChannel.open();
? ? ? ? ? ? channel.configureBlocking(false);
? ? ? ? ? ? //请求连接
? ? ? ? ? ? channel.connect(new InetSocketAddress("localhost", 8383));
? ? ? ? ? ? selector = Selector.open();
? ? ? ? ? ? channel.register(selector, SelectionKey.OP_CONNECT);
? ? ? ? ? ? boolean isOver = false;
? ? ? ? ? ?
? ? ? ? ? ? while(! isOver){
? ? ? ? ? ? ? ? selector.select();
? ? ? ? ? ? ? ? Iterator ite = selector.selectedKeys().iterator();
? ? ? ? ? ? ? ? while(ite.hasNext()){
? ? ? ? ? ? ? ? ? ? SelectionKey key = (SelectionKey) ite.next();
? ? ? ? ? ? ? ? ? ? ite.remove();
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? if(key.isConnectable()){
? ? ? ? ? ? ? ? ? ? ? ? if(channel.isConnectionPending()){
? ? ? ? ? ? ? ? ? ? ? ? ? ? if(channel.finishConnect()){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //只有当连接成功后才能注册OP_READ事件
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? key.interestOps(SelectionKey.OP_READ);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? channel.write(CharsetHelper.encode(CharBuffer.wrap(getWord())));
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sleep();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? key.cancel();
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else if(key.isReadab