日期:2014-05-16  浏览次数:21037 次

Apache MINA瀛︿範涔嬭矾(4)

聽 聽 聽 聽鏌ョ湅 Mina 瀵?TextLineCodec 鐨勫疄鐜版簮鐮佷細鍙戠幇锛屾牴鎹崲琛岀瑙g爜鐨勬秷鎭犻粯璁ゆ渶澶ч暱搴︽槸 1024锛?鐩稿綋浜庣紦鍐插尯鏈€澶ц兘瀛樻斁 1K 鐨勬暟鎹€傛墍浠ヤ娇鐢ㄦ椂锛屽缓璁皟鏁村弬鏁颁负 2K锛?/p>

聽 聽 聽 聽鏍规嵁鎴戜滑鑷繁瀹氫箟鐨勬枃鏈崲琛岀鍙婄紪鐮佹牸寮忕紪瑙g爜锛?鍒欓渶瑕佹妸瀹冧滑浣滀负鍙傛暟浼犻€掔粰缂栬В鐮佸櫒锛涘畬鏁翠唬鐮佸涓嬶細

瑙g爜鍣?/p>

import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

public class MyCodecDecoderII implements ProtocolDecoder {
	private Charset charset; // 缂栫爜鏍煎紡
	private String delimiter; // 鏂囨湰鍒嗛殧绗?
	private IoBuffer delimBuf; // 鏂囨湰鍒嗗壊绗﹀尮閰嶇殑鍙橀噺

	// 瀹氫箟甯搁噺鍊硷紝浣滀负姣忎釜IoSession涓繚瀛樿В鐮佷换鍔$殑key鍊?
	private static String CONTEXT = MyCodecDecoderII.class.getName()
			+ ".context";

	// 鏋勯€犲嚱鏁帮紝蹇呴』鎸囧畾Charset鍜屾枃鏈垎闅旂
	public MyCodecDecoderII(Charset charset, String delimiter) {
		this.charset = charset;
		this.delimiter = delimiter;
	}

	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
			throws Exception {
		Context ctx = getContext(session);
		// 濡傛灉鏂囨湰鎹㈣绗︽湭鎸囧畾锛屼娇鐢ㄩ粯璁ゅ€?
		if (delimiter == null || "".equals(delimiter)) {
			delimiter = "\r\n";
		}
		if (charset == null) {
			charset = Charset.forName("utf-8");
		}
		decodeNormal(ctx, in, out);
	}

	// 浠嶪oSession涓幏鍙朇ontext瀵硅薄
	private Context getContext(IoSession session) {
		Context ctx;
		ctx = (Context) session.getAttribute(CONTEXT);
		if (ctx == null) {
			ctx = new Context();
			session.setAttribute(CONTEXT, ctx);
		}
		return ctx;
	}

	// 瑙g爜
	private void decodeNormal(Context ctx, IoBuffer in,
			ProtocolDecoderOutput out) throws CharacterCodingException {
		// 鍙栧嚭鏈畬鎴愪换鍔′腑宸茬粡鍖归厤鐨勬枃鏈崲琛岀鐨勪釜鏁?
		int matchCount = ctx.getMatchCount();
		// 璁剧疆鍖归厤鏂囨湰鎹㈣绗︾殑IoBuffer鍙橀噺
		if (delimBuf == null) {
			IoBuffer tmp = IoBuffer.allocate(2).setAutoExpand(true);

			tmp.putString(delimiter, charset.newEncoder());
			tmp.flip();
			delimBuf = tmp;
		}

		int oldPos = in.position(); // 瑙g爜鐨処oBuffer涓暟鎹殑鍘熷淇℃伅
		int oldLimit = in.limit();
		while (in.hasRemaining()) { // 鍙橀噺瑙g爜鐨処oBuffer
			byte b = in.get();
			if (delimBuf.get(matchCount) == b) { // 鍖归厤绗琺atchCount浣嶆崲琛岀鎴愬姛
				matchCount++;
				if (matchCount == delimBuf.limit()) { // 褰撳墠鍖归厤鍒板瓧鑺備釜鏁颁笌鏂囨湰鎹㈣绗﹀瓧鑺備釜鏁扮浉鍚岋紝鍖归厤缁撴潫
					int pos = in.position(); // 鑾峰緱褰撳墠鍖归厤鍒扮殑position锛坧osition鍓嶆墍鏈夋暟鎹湁鏁堬級
					in.limit(pos);
					in.position(oldPos); // position鍥炲埌鍘熷浣嶇疆
					ctx.append(in); // 杩藉姞鍒癈ontext瀵硅薄鏈畬鎴愭暟鎹悗闈?
					in.limit(oldLimit); // in涓尮閰嶇粨鏉熷悗鍓╀綑鏁版嵁
					in.position(pos);
					IoBuffer buf = ctx.getBuf();
					buf.flip();
					buf.limit(buf.limit() - matchCount);// 鍘绘帀鍖归厤鏁版嵁涓殑鏂囨湰鎹㈣绗?
					try {
						out.write(buf.getString(ctx.getDecoder())); // 杈撳嚭瑙g爜鍐呭
					} finally {
						buf.clear(); // 閲婃斁缂撳瓨绌洪棿
					}
					oldPos = pos;
					matchCount = 0;
				}
			} else {
				// 濡傛灉matchCount==0锛屽垯缁х画鍖归厤
				// 濡傛灉matchCount>0锛岃鏄庢病鏈夊尮閰嶅埌鏂囨湰鎹㈣绗︾殑涓殑鍓嶄竴涓尮閰嶆垚鍔熷瓧鑺傜殑涓嬩竴涓瓧鑺傦紝
				// 璺宠浆鍒板尮閰嶅け璐ュ瓧绗﹀锛屽苟缃甿atchCount=0锛岀户缁尮閰?
				in.position(in.position() - matchCount);
				matchCount = 0; // 鍖归厤鎴愬姛鍚庯紝matchCount缃┖

			}
		}
		// 鎶奿n涓湭瑙g爜鍐呭鏀惧洖buf涓?
		in.position(oldPos);
		ctx.append(in);
		ctx.setMatchCount(matchCount);
	}

	public void dispose(IoSession session) throws Exception {
	}

	public void finishDecode(IoSession session, ProtocolDecoderOutput out)
			throws Exception {
	}

	// 鍐呴儴绫伙紝淇濆瓨IoSession瑙g爜鏃舵湭瀹屾垚鐨勪换鍔?
	private class Context {
		private CharsetDecoder decoder;
		private IoBuffer buf; // 淇濆瓨鐪熷疄瑙g爜鍐呭
		private int matchCount = 0; // 鍖归厤鍒扮殑鏂囨湰鎹㈣绗︿釜鏁?

		private Context() {
			decoder = charset.newDecoder();
			buf = IoBuffer.allocate(80).setAutoExpand(true);
		}

		// 閲嶇疆
		public void reset() {
			matchCount = 0;
			decoder.reset();
		}

		// 杩藉姞鏁版嵁
		public void append(IoBuffer in) {
			getBuf().pu