学习笔记—JavaNIO阻塞通信
public class EchoServer {ServerSocketChannel serverSocketChannel;ExecutorService executorService;public EchoServer() throws Exception{// 根据CPU数创建线程池executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2);// 创建ServerSocketChannel对象// 每个ServerSocketChannel对象都与一个ServerSocket对象关联// 此时没有与任何端口绑定并处于阻塞模式serverSocketChannel= ServerSocketChannel.open();// socket方法返回与之关联的ServerSocket对象,此处设置socket可以复用serverSocketChannel.socket().setReuseAddress(true);// 绑定端口serverSocketChannel.socket().bind(new InetSocketAddress(8080));System.out.println("服务器已启动");}public void service(){while(true){SocketChannel socketChannel = null;try {// 阻塞等待客户端socketChannel = serverSocketChannel.accept();// 提交给线程池执行,runnable一个任务executorService.execute(new Handler(socketChannel));} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) throws Exception {new EchoServer().service();}}// 执行的业务逻辑,传入每个socket客户端class Handler implements Runnable{private SocketChannel socketChannel;public Handler(SocketChannel socketChannel) {this.socketChannel = socketChannel;}@Overridepublic void run() {// 取得通道对应的SocketSocket socket = socketChannel.socket();System.out.println("客户端连接:"+socket.getInetAddress()+":"+socket.getPort());try {//BufferedReader br = getReader(socket);//PrintWriter pw = getWriter(socket);readLine(socketChannel);//String msg = null;//while((msg=br.readLine())!=null){//System.out.println(msg);//pw.println(echo(msg));//if(msg.equals("88")){//break;//}//}} catch (Exception e) {e.printStackTrace();} finally{if(socketChannel!=null){try {socketChannel.close();} catch (IOException e) {e.printStackTrace();}}}}private String echo(String msg) {return "echo:"+msg;}private BufferedReader getReader(Socket socket) throws Exception{// 取得Socket的输入流InputStream in = socket.getInputStream();return new BufferedReader(new InputStreamReader(in));}private PrintWriter getWriter(Socket socket) throws Exception{OutputStream out = socket.getOutputStream();return new PrintWriter(out,true);}// 采用缓冲区来读取数据,极限、位置等看打印结果就能清楚了public String readLine(SocketChannel socketChannel) throws IOException {// 创建1024大小的缓冲区ByteBuffer buffer = ByteBuffer.allocate(1024);// 一个字节的缓冲区ByteBuffer temp = ByteBuffer.allocate(1);boolean isLine = false;boolean isEnd = false;String data = null;// 当一行没有结束,并且没有到达结尾while(!isLine&&!isEnd){// 清除缓冲区,极限设为容量temp.clear();// 阻塞模式,只要读取1个字节或末尾才返回// 非阻塞模式,可能返回0int n = socketChannel.read(temp);if(n==-1){isEnd = true;break;}if(n==0){continue;}System.out.println("开始位置="+buffer.position());System.out.println("开始极限="+buffer.limit());System.out.println("开始容量="+buffer.capacity());// 极限设为位置,位置设为0// 只有极限以内可以读写temp.flip();// 复制内容到buffer中buffer.put(temp);System.out.println("写入buffer位置="+buffer.position());System.out.println("写入buffer极限="+buffer.limit());System.out.println("写入buffer容量="+buffer.capacity());// 把极限设为写入数据的位置buffer.flip();System.out.println("flip后位置="+buffer.position());System.out.println("flip后极限="+buffer.limit());System.out.println("flip后容量="+buffer.capacity());Charset charset = Charset.forName("GBK");CharBuffer charBuffer = charset.decode(buffer);data = charBuffer.toString();if(data.indexOf("\r\n")!=-1){// 如果有回车换行,一行结束isLine = true;// 切除回车换行data = data.substring(0, data.indexOf("\r\n"));break;}System.out.println("位置="+buffer.position());System.out.println("极限="+buffer.limit());System.out.println("容量="+buffer.capacity());// 位置设为极限,为下次读取准备buffer.position(buffer.limit());// 把极限设为容量buffer.limit(buffer.capacity());}return data;}}
?
?