博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android版Web服务器实现(二)使用服务来监听HTTP请求
阅读量:7227 次
发布时间:2019-06-29

本文共 6196 字,大约阅读时间需要 20 分钟。

《》一文中说到了HTTP协议请求头的解析,那么我们要如何得到这个HTTP请求头呢?我们需要监听端口。监听是一直要运行着的,在Android中比较好的方式就是使用服务。下面是实现的代码。

WebServer.java

package com.sparkle.webservice;import java.io.IOException;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.ServerSocket;import android.app.Service;import android.content.Context;import android.content.Intent;import android.net.wifi.WifiManager;import android.os.IBinder;import android.util.Log;import com.sparkle.kits.IP;public class WebServer extends Service implements Runnable {	private static boolean _isRunning = false;	private static Thread _serverThread = null;	private ServerSocket _listenSocket = null;	private MyLog _myLog = new MyLog(getClass().getName());	private static int _port = Defaults.getPort();	private TcpListener _tcpListener = null;	private static final int WAKE_INTERVAL_MS = 1000;	public WebServer() {		try {			Init();		} catch (IOException e) {			e.printStackTrace();		}	}	private void Init() throws IOException {		_listenSocket = new ServerSocket();		_listenSocket.setReuseAddress(true);		_listenSocket.bind(new InetSocketAddress(_port));	}	public static void Start(Context context) {		if (!_isRunning) {			_isRunning = true;			Intent intent = new Intent(context, WebServer.class);			context.startService(intent);		}	}	public static void Stop(Context context) {		if (_isRunning) {			_isRunning = false;			Intent intent = new Intent(context, WebServer.class);			context.stopService(intent);		}	}	public static boolean isRunning() {		return _isRunning;	}	@Override	public int onStartCommand(Intent intent, int flags, int startId) {		int attempts = 10;		// The previous server thread may still be cleaning up,		// wait for it to finish.		while (_serverThread != null) {			_myLog.l(Log.WARN, "Won't start, server thread exists");			if (attempts <= 0) {				_myLog.l(Log.ERROR, "Server thread already exists");				return super.onStartCommand(intent, flags, startId);			}			try {				Thread.sleep(1000);			} catch (InterruptedException e) {				// TODO Auto-generated catch block				e.printStackTrace();			}			attempts--;		}		_myLog.l(Log.DEBUG, "Creating server thread");		_serverThread = new Thread(this);		_serverThread.start();		return super.onStartCommand(intent, flags, startId);	}	@Override	public void onDestroy() {		if (_tcpListener != null) {			_tcpListener.quit();		}		_myLog.l(Log.INFO, "onDestroy() Stopping server");		if (_serverThread == null) {			_myLog.l(Log.WARN, "Stopping with null serverThread");			return;		}		_serverThread.interrupt();		try {			_serverThread.join(10000); // wait 10 second for server thread to										// finish		} catch (InterruptedException e) {		}		if (_serverThread.isAlive()) {			_myLog.l(Log.WARN, "Server thread failed to exit");		} else {			_myLog.d("serverThread joined ok");			_serverThread = null;		}		try {			if (_listenSocket != null) {				_listenSocket.close();			}		} catch (IOException e) {			// TODO Auto-generated catch block			e.printStackTrace();		}		UiUpdater.updateClients();		_myLog.d("WebService.onDestroy() finished");	}	@Override	public IBinder onBind(Intent intent) {		return null;	}	@Override	public void run() {// Server thread run.		while (_isRunning) {			UiUpdater.updateClients();			if (_tcpListener == null) {				_tcpListener = new TcpListener(_listenSocket, this);				_tcpListener.start();			}			try {				Thread.sleep(WAKE_INTERVAL_MS);			} catch (InterruptedException e) {				_myLog.l(Log.DEBUG, "Thread interrupted");			}		}	}	public static InetAddress getWifiIp(Context context) {		if (context == null) {			throw new NullPointerException("Global context is null");		}		WifiManager wifiManager = (WifiManager) context				.getSystemService(Context.WIFI_SERVICE);		if (!wifiManager.isWifiEnabled()) {			return null;		}		int ipAsInt = wifiManager.getConnectionInfo().getIpAddress();		if (ipAsInt == 0) {			return null;		} else {			return IP.intToInet(ipAsInt);		}	}	public static int getPort() {		return _port;	}}
注:

1、WebServer继承自Service,内部套了一个服务的线程,所以又实现了Runnable接口。

2、重载onStartCommand方法,在该方法中启动服务线程_serverThread。在启动时,进行探测,以确保前一次启动的_serverThread已经关闭。

3、重载onDestroy方法,在该方法中关闭服务线程。

4、在run方法中,启用监听_tcpListener。TcpListener是一个封装的类,具体参看后面的代码。

5、附上getWifiIp和getPort方法,以方便调用。

6、UiUpdater是一个界面更新器,具体的请参看后文的代码。

7、服务需要在AndroidManifest.xml中注册,注册部分代码如下。

AndroidManifest.xml部分代码

TcpListener.java

package com.sparkle.webservice;import java.net.ServerSocket;import java.net.Socket;import android.util.Log;public class TcpListener extends Thread {	private ServerSocket _listenSocket = null;	private MyLog _myLog = new MyLog(getClass().getName());	public TcpListener(ServerSocket listenSocket, WebServer webServer) {		this._listenSocket = listenSocket;	}	public void quit() {		try {			_listenSocket.close(); // if the TcpListener thread is blocked on									// accept,									// closing the socket will raise an									// exception		} catch (Exception e) {			_myLog.l(Log.DEBUG, "Exception closing TcpListener listenSocket");		}	}	public void run() {		try {			while (true) {				Socket clientSocket = _listenSocket.accept();				_myLog.l(Log.INFO, "New connection, spawned thread");				SessionThread newSession = new SessionThread(clientSocket);				newSession.start();							}		} catch (Exception e) {			_myLog.l(Log.DEBUG, "Exception in TcpListener");		}	}}
注:

1、在run中使用accept的阻塞方法来监听。

2、在收到请求后,放到SessionThread中去处理,该部分代码请参看后文。

3、MyLog是自定义的一个日志类。

MyLog.java

package com.sparkle.webservice;import android.util.Log;public class MyLog {	protected String tag;	public MyLog(String tag) {		this.tag = tag;	}	public void l(int level, String str, boolean sysOnly) {		synchronized (MyLog.class) {			str = str.trim();			Log.println(level, tag, str);		}	}	public void l(int level, String str) {		l(level, str, false);	}	public void e(String s) {		l(Log.ERROR, s, false);	}	public void w(String s) {		l(Log.WARN, s, false);	}	public void i(String s) {		l(Log.INFO, s, false);	}	public void d(String s) {		l(Log.DEBUG, s, false);	}}
注:日志输出时使用synchronized来确保日志的输出。

监听到了HTTP的请求后,需要对其进行处理以作出响应,具体请看下一篇。

转载请注明出处:

转载于:https://www.cnblogs.com/sparkleDai/p/7605026.html

你可能感兴趣的文章
linux分区方案
查看>>
003-Java技术体系
查看>>
超轻量模板引擎
查看>>
JavaScript 复习之 Object对象的相关方法
查看>>
JAVA之流程控制语句
查看>>
Spring Boot(1)
查看>>
Winodws 10 美化与调优
查看>>
apache安装及多域名解析及域名代理
查看>>
什么是自动化运维 ? 自动化运维的设计思路以及实战
查看>>
Python练习实例100例(持续更新中)
查看>>
非父组件通信
查看>>
Electron系列文章-主进程与渲染进程
查看>>
高性能缓存服务器 nuster v1.8.8.2 和 v1.7.11.2 发布
查看>>
教你快速入门ES6
查看>>
Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery
查看>>
宜昌a货翡翠,包头a货翡翠
查看>>
【微信事业群】趣味面试算法题
查看>>
保守的国美再一次进击社交电商,前途未卜?
查看>>
git
查看>>
Python学习教程(Python学习路线):Python 3—手动创建迭代器
查看>>