移动开发中的通信架构(三)

        前面两篇文章讲述了框架的大体情况和请求的封装,这篇文章讲述请求的发送。在本框架中,请求生成以后,并不是马上发送,而是加入一个请求列表。然后有一个线程来维护这个请求列表。

        下面来具体分析,从移动开发中的通信架构(二)的第一段代码中取出:

sendRequest(request);

sendRequest方法由HttpHandler类提供,下面是HttpHandler的源代码:

package app.http;

import java.util.Vector;

/**
 * 
 *在调用sendRequest方法的时候,其实并没有发生真正的网络请求,仅仅是把Request对象加入到了请求列表vctRequests中
 *
 *在以后的设计中,注意vctRequests要保持线程安全的特性,因为UI和网络线程都会不停的调用它
 *
 */

/**
 * 功能:
 * 
 * 联系    整个程序的控制类    和    真正的网络类,其实也就是网络模块中的控制类
 * 
 * 维护一个列表,从程序中接受Request,然后把Request转发给HttpClient
 */
public class HttpHandler implements Timeable, Runnable {

	private boolean isRunning = false;
	// Http client
	private HttpClient httpClient = null;
	// 超时时间
	private int timeout;
	// 重新连接次数
	private int retries;
	// HttpListener
	private HttpListener httpListener = null;
	// Http监视器
	private HttpMonitor monitor = null;

	// 等待发送的缓冲请求信息
	private Vector vctRequests = new Vector();

	private int state = STATE_REST;
	private final static int STATE_REST = 0;
	private final static int STATE_CANCEL = 1;
	private final static int STATE_ACTIVE = 2;

	public HttpHandler(HttpListener httpListener, int _msgId) {
		this(HttpConstants.DEFAULT_OVERTIME, HttpConstants.DEFAULT_RETRIES, httpListener, _msgId);
	}

	public HttpHandler(int timeout, int retries, HttpListener httpListener, int _msgId) {
		this.retries = retries;
		this.timeout = timeout;
		this.httpListener = httpListener;
		this.isRunning = true;
		httpClient = new HttpClient(_msgId);

		Thread t = new Thread(this);
		t.start();

	}

	/**
	 * 设置监听器 (多用于屏幕切换后更改监听器用)
	 * 
	 * @param httpListener
	 */
	public void setHttpListener(HttpListener httpListener) {
		this.httpListener = httpListener;
	}

	public void run() {
		while (isRunning) {
			try {
				if (vctRequests.size() > 0) {
					Request request = null;
					synchronized (vctRequests) {
						if (vctRequests.size() > 0) {
							request = (Request) vctRequests.elementAt(0);
							vctRequests.removeElementAt(0);
						}
					}

					Response resp = getResponse(request);

					// 数据到达
					if (resp != null) {
						if (httpListener != null) {
							httpListener.completed(resp);
						}
						resp = null;
					}
				}
				Thread.sleep(200);
			} catch (Exception ex) {

			}
		}
	}

	private void handleException(Exception ex) {
		if (httpListener != null && state == STATE_ACTIVE) {
			try {
				httpListener.exception(ex, this);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Provides an interrupt to the initiated request. This method is typically
	 */
	public void timeout() {

		// 数据接收超时
		cleanup();

		handleException(new Exception("网络连接超时..."));
	}

	/**
	 * 发送Request
	 * 
	 * @param request
	 */
	public void sendRequest(Request request) {
		if (request == null) {
			return;
		}

		synchronized (vctRequests) {
			vctRequests.addElement(request);
		}
	}

	/**
	 * 接收数据
	 * 
	 * @return
	 */
	public Response getResponse(Request request) {
		Response resp = null;

		int thisTry = 1;
		while (thisTry <= retries) {
			try {
				startTimer();
				state = STATE_ACTIVE;
				httpListener.netSatus("正在进行网络连接...");
				/**
				 * 核心语句
				 */
				resp = httpClient.getResponse(request);

				stopTimer();
				state = STATE_REST;
				break;
			} catch (Exception e) {
				e.printStackTrace();
				stopTimer();
				if (state == STATE_CANCEL) {
					state = STATE_REST;
					break;
				} else if (thisTry >= retries) {
					cleanup();
					handleException(new Exception("网络连接失败..."));
				}
				state = STATE_REST;
			} finally {
				thisTry++;
			}
		}

		return resp;
	}

	/**
	 * 关闭连接,释放相关资源
	 */
	private void cleanup() {
		try {
			// 关闭监视器
			this.cancelTimer();
			monitor = null;

			// 回收http资源
			httpClient.cleanup();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取当前发送信息的条数
	 * 
	 * @return int
	 */
	public int getVctRequests() {
		synchronized (vctRequests) {
			return vctRequests.size();
		}
	}

	/**
	 * 中断线程
	 */
	public void stop() {
		// 请空缓存请求数据
		synchronized (vctRequests) {
			vctRequests.removeAllElements();
		}

		httpListener = null;
		cleanup();

		// 中断数据接收监听
		isRunning = false;
		httpClient = null;

	}

	public void cancelAccess() {
		if (state == STATE_ACTIVE) {
			state = STATE_CANCEL;
			cleanup();
		}
	}

	public void startTimer() {
		if (timeout > 0) {
			monitor = getRequestTimer();
			monitor.startTimer();
		}
	}

	private HttpMonitor getRequestTimer() {
		if (monitor == null) {
			monitor = new HttpMonitor(this, timeout);
			monitor.start();
		}
		return monitor;
	}

	/**
	 * Issues a stopTimer() call to the <code>SocketMonitor</code>.
	 * 
	 * @see java.io.InputStream
	 */
	public void stopTimer() {
		if (timeout > 0 && monitor != null) {
			monitor.stopTimer();
		}
	}

	/**
	 * Issues a cancelTimer() call to the <code>SocketMonitor</code>.
	 */
	public void cancelTimer() {
		if (timeout > 0) {
			if (monitor != null) {
				monitor.cancelTimer();
			}
		}
	}

	public void pauseTimer() {
		if (monitor != null) {
			monitor.pauseMonitor();
		}
	}

	public void resumeTimer() {
		if (monitor != null) {
			monitor.resumeMonitor();
		}
	}

}


请读者自行关注里面的重要方法,本人只是罗列一下:

public void run();

public void sendRequest(Request request);

public Response getResponse(Request request);

从程序代码中可以看到,HttpHandler是整个通信框架的耦合点:

1.它借助于下一篇讲述的Httpclient来实现请求的发送。

2.它借助于Timeable和HttpMonitor实现超时的控制。

3.它借助于HttpListener完成和UI线程的沟通。

 

下面罗列Timeable和HttpMonitor的源代码,超时的控制比较简单,我就不详细讲述。

package app.http;

/**
 * 计时器辅助接口
 */
public interface Timeable {

	public void timeout();

	public void startTimer();

	public void stopTimer();

	public void cancelTimer();
}


 

 

package app.http;

/**
 *计时器类,主要用于监控http连接是否超时
 */
public class HttpMonitor extends Thread {
	// 超时时间(毫秒)
	private long timeout;
	private Timeable timeable;
	private long startTime;
	private boolean active = false;
	private boolean timing = false;
	private boolean bPaused = false;

	public HttpMonitor(Timeable t, int timeout) {
		this.timeout = timeout * 1000;
		timeable = t;
		timing = false;
	}

	public void pauseMonitor() {
		bPaused = true;
	}

	public void resumeMonitor() {
		startTime = System.currentTimeMillis();
		bPaused = false;
	}

	public void run() {
		active = true;
		while (active) {
			if (timing) {
				long tmp = System.currentTimeMillis() - startTime;
				if (!bPaused && (tmp) > timeout) {
					timeable.timeout();
					stopTimer();
				} else {
					try {
						sleep(HttpConstants.MONITOR_INTERVAL);
					} catch (InterruptedException ie) {
						active = false;
					}
				}
			} else {
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					e.printStackTrace();
					active = false;
				}
			}
		}
	}

	public void startTimer() {
		if (!timing) {
			startTime = System.currentTimeMillis();
			timing = true;
		}
	}

	public void setTimeout() {
		try {
			stopTimer();
			timeable.timeout();
		} catch (Exception ex) {
		}
	}

	public void stopTimer() {
		timing = false;
	}

	public void cancelTimer() {
		active = false;
		timing = false;
		synchronized (this) {
			notifyAll();
		}
	}

	public long getTimeout() {
		return timeout / 1000;
	}
}


 

ps:有任何疑问可以留言,回复可能不及时,但是有意义的疑问一定回复。

ps:记得看到好文章好顶……

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值