/** * Copyright (c) 2005-2012 https://github.com/zhangkaitao * * Licensed under the Apache License, Version 2.0 (the "License"); */ package com.sishuok.chapter4.web.upgrade.server; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpUpgradeHandler; import javax.servlet.http.WebConnection; import java.io.IOException; /** * <p>User: Zhang Kaitao * <p>Date: 13-7-20 下午10:59 * <p>Version: 1.0 */ public class EchoHttpUpgradeHandler implements HttpUpgradeHandler { private ServletInputStream is; private ServletOutputStream os; /** * HTTP Upgrade 升级完成时回调一次(仅一次),接着可以使用新协议来进行客户端/服务器通信(此时容器完全不知道细节) * 使用WebConnection连接进行通信,通过它可以获取输入输出流(可以以非阻塞I/O通信) * * @param wc */ @Override public void init(final WebConnection wc) { try { is = wc.getInputStream(); os = wc.getOutputStream(); //采用非阻塞I/O读写 is.setReadListener(new EchoReadListener()); //刷出下(如写出的响应头) os.flush(); } catch (IOException e) { e.printStackTrace(); } } /** * 当客户端断开连接时回调 */ @Override public void destroy() { System.out.println("===连接终止"); } private class EchoReadListener implements ReadListener { private StringBuilder buffer = new StringBuilder(); @Override public void onDataAvailable() throws IOException { int ch = -1; while(is.isReady() && ((ch = is.read()) != -1)) { buffer.append((char)ch); int bufferLength = buffer.length(); //如果接收到的是CRLF,表示一次读取完毕 if(bufferLength >= 2 && buffer.charAt(bufferLength - 2) == '\r' && buffer.charAt(bufferLength - 1) == '\n') { String data = buffer.toString(); if("BYE\r\n".equals(data)) {//结束通信 System.out.println("服务器结束通信:" + data); os.close(); is.close(); break; } else {//否则把数据加入队列,由WriteListener写 System.out.println("服务器接收到数据:" + data); os.write(data.getBytes("ISO-8859-1")); os.flush(); buffer = new StringBuilder(); } } } } @Override public void onAllDataRead() throws IOException { } @Override public void onError(final Throwable t) { System.out.println("服务器端读出错了"); t.printStackTrace(System.out); try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }