mina_server

http协议header中,异步socket(nio、mina)中必须指定其Content-Length的长度,才算结束。

/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *  
 *    http://www.apache.org/licenses/LICENSE-2.0
 *  
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License. 
 *  
 */
package org.apache.mina.example.httpserver.stream;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;
import org.apache.mina.common.support.BaseByteBuffer;
import org.apache.mina.filter.codec.ProtocolDecoderException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pica.common.CommonUtils;
import com.pica.config.Dispatch;
import com.pica.server.BaseAction;
import com.pica.server.Request;
import com.pica.server.action.FetchEventAction;

/**
 * A simplistic HTTP protocol handler that replies back the URL and headers
 * which a client requested.
 * 
 * @author The Apache Directory Project ([email protected])
 * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007)
 *          $
 */
public class HttpProtocolHandler extends IoHandlerAdapter {

	private static final Logger Log = LoggerFactory.getLogger(HttpProtocolHandler.class);

	public void sessionOpened(IoSession session) throws Exception {
		Log.debug("ConnectionHandler: sessionOpened.");
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		Log.debug("ConnectionHandler: sessionClosed.");
	}

	/**
	 * Invoked when a MINA session has been idle for half of the allowed XMPP
	 * session idle time as specified by {@link #getMaxIdleTime()}. This method
	 * will be invoked each time that such a period passes (even if no IO has
	 * occurred in between).
	 * 
	 * Openfire will disconnect a session the second time this method is
	 * invoked, if no IO has occurred between the first and second invocation.
	 * This allows extensions of this class to use the first invocation to check
	 * for livelyness of the MINA session (e.g by polling the remote entity, as
	 * {@link ClientConnectionHandler} does).
	 * 
	 * 两次心跳时间内没有消息交互就断开连接
	 * 
	 * @see org.apache.mina.common.IoHandlerAdapter#sessionIdle(org.apache.mina.common.IoSession,
	 *      org.apache.mina.common.IdleStatus)
	 */
	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		// Close idle connection
		Log.debug("ConnectionHandler:sessionIdle. Closing connection that has been idle: " + status);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		if (cause instanceof IOException) {
			Log.debug("ConnectionHandler: ", cause);
		} else if (cause instanceof ProtocolDecoderException) {
			Log.warn("Closing session due to exception: " + session, cause);
			session.close();
		} else {
			Log.error(cause.getMessage(), cause);
		}
	}

	public void messageReceived(IoSession session, Object message) throws Exception {
		super.messageReceived(session, message);
		Log.debug(session.hashCode() + ":" + this.hashCode() + ":messageReceived:" + message.getClass() + "\t" + message);
		org.apache.mina.common.support.BaseByteBuffer buffer = (org.apache.mina.common.support.BaseByteBuffer) message;
		
		InputStream in = buffer.asInputStream();
		String url;
		Map<String, String> headers = new TreeMap<String, String>();
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		int timeout = 0;
		StringBuffer sb = new StringBuffer();
		try {
			// Get request URL.
			url = br.readLine();
			if (url == null) {
				Log.debug("nowTime:"+new Date().getTime());
				Log.debug("getLastIoTime:"+session.getLastIoTime());
				Log.debug("getLastReadTime:"+session.getLastReadTime());
				Log.debug("getLastWriteTime:"+session.getLastWriteTime());
				return;
			}
			url = url.split(" ")[1];
			Log.debug("url:"+url);
			String baseUrl = CommonUtils.getBaseUrl(url);
			Log.debug("baseUrl:"+baseUrl);
			if(baseUrl.endsWith("/aim/fetchEvents")){
				baseUrl = "/aim/fetchEvents";
			}
			Map<String, String> parameter = CommonUtils.getParameter(url);

			// Read header
			String line;
			while ((line = br.readLine()) != null && !line.equals("")) {
				String[] tokens = line.replaceAll(" ", "").split(":");
				headers.put(tokens[0], tokens[1]);
			}
			String zlass = Dispatch.getDispatch(baseUrl);
			if (zlass != null) {
				Object obj = Class.forName(zlass).newInstance();
				if (obj instanceof BaseAction) {
					BaseAction action = (BaseAction) obj;
					timeout = action.doGet(new Request(in, headers, parameter), sb);
				} else {
					String notfound = "<html><head><title>Not Found</title></head><body><h1>Error 500-class [" + zlass + "] not extends com.pica.server.BaseAction</h1></body></html>";
					sb.append("HTTP/1.0 500 Internal Server Error\n");
					sb.append("Content_Type:text/html\n");
					sb.append("Content-Length:"+notfound.getBytes().length+"\t");
					sb.append("\r\n\r\n");
					sb.append(notfound);
					return;
				}
			} else {
				String notfound = "<html><head><title>Not Found</title></head><body><h1>Error 404-file [" + url + "] not found</h1></body></html>";
				sb.append("HTTP/1.0 404 no found\n");
				sb.append("Content_Type:text/html\n");
				sb.append("Content-Length:"+notfound.getBytes().length+"\t");
				
				sb.append("\r\n\r\n");
				sb.append(notfound);
				return;
			}

		} catch (Exception e) {
			sb.append("HTTP/1.0 500 Internal Server Error\n");
			sb.append("Content_Type:text/html\n");
			sb.append("Content-Length:"+e.getMessage().getBytes().length+"\t");
			sb.append("\r\n\r\n");
			sb.append(e.getMessage());
		} finally {
			//sb.append("\r\n\r\n");
			if(timeout > 0){
				try {
					Thread.sleep(timeout);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			session.write(BaseByteBuffer.wrap(sb.toString().getBytes()));
		}
		
		
		
	}

	public void messageSent(IoSession session, Object message) throws Exception {
		super.messageSent(session, message);
		org.apache.mina.common.support.BaseByteBuffer buffer = (org.apache.mina.common.support.BaseByteBuffer) message;
		InputStream in = buffer.asInputStream();
		byte[] b = new byte[in.available()];
		in.read(b);
		Log.debug("###############################################################################################################");
		Log.debug(session.hashCode() + ":" + this.hashCode() + ":messageSent:" + message.getClass() + "\t" + new String(b));
		Log.debug("###############################################################################################################");
	}

}

你可能感兴趣的:(header,Mina,Content-Length)