public class MainActivity extends AppCompatActivity {
private SimpleHttpServer shs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置端口与最大监听数
WebConfiguration wed = new WebConfiguration(8078, 50);
shs = new SimpleHttpServer(wed);
//注册路由
shs.reqisterResourceHandler(new UploadImageHandler());
shs.reqisterResourceHandler(newResourceInAssetsHandler(MainActivity.this));
//启动服务器
shs.startAsync();
}
@Override
protected void onDestroy() {
try {
shs.stopAsync();
} catch (IOException e) {
e.printStackTrace();
}
super.onDestroy();
}
}
class WebConfiguration {
/**
* 端口号
*/
private int port;
/**
* 最大监听数
*/
private int maxParallels;
public WebConfiguration(int port,int maxParallels){
this.port=port;
this.maxParallels=maxParallels;
}
public void setPort(int port){
this.port=port;
}
public void setMaxParallels(int maxParallels){
this.maxParallels=maxParallels;
}
public int getPort(){
return this.port;
}
public int getMaxParallels(){
return this.maxParallels;
}
}
public class SimpleHttpServer {
private final ExecutorService threadPoob;
private boolean isEnable;
private WebConfiguration web;
private ServerSocket socket;
private Socket remotePeer;
private Set<IResourceUriHandler> resourceHandler;
public SimpleHttpServer(WebConfiguration web){
this.web=web;
/**
* 在构造里创建线程池与Set集合
* Set集合存储路由
* 线程池对Socket操作
*/
threadPoob = Executors.newCachedThreadPool();
resourceHandler=new HashSet<>();
}
/**
* Android对耗时操作都得异步执行
*/
public void startAsync(){
isEnable=true;
new Thread(new Runnable() {
@Override
public void run() {
doProcSync();
}
}).start();
}
public void stopAsync() throws IOException {
if(!isEnable){
return;
}
isEnable=false;
if(socket!=null){
socket.close();
socket=null;
}
}
private void doProcSync() {
try {
InetSocketAddress socketaddress=new InetSocketAddress(web.getPort());
socket=new ServerSocket();
/**
* 绑定端口号
*/
socket.bind(socketaddress);
while (isEnable){
/**
* 阻塞,等待客户端
*/
remotePeer = socket.accept();
/**
* 扔到线程池
*/
threadPoob.submit(new Runnable() {
@Override
public void run() {
onAcceptRemotePeer(remotePeer);
}
});
}
} catch (IOException e) {
Log.e("doProcSync",e.toString());
e.printStackTrace();
}
}
private void onAcceptRemotePeer(Socket remotePeer) {
try {
/**
* HttpConntext 存储Socket的请求信息与Scoket
*/
HttpConntext httpConntext=new HttpConntext();
httpConntext.setUnderlySocke(remotePeer);
/**
* 读取请求信息
*/
InputStream inputStream = remotePeer.getInputStream();
String headerLine=null;
String resourceUri=headerLine=StreamToolkit.reabLing(inputStream).split(" ")[1];
Log.e("spy",resourceUri);
while ((headerLine=StreamToolkit.reabLing(inputStream))!=null) {
if (headerLine.equals("\r\n")) {
break;
}
Log.e("spy", headerLine);
String[] requestheader=headerLine.split(":");
httpConntext.addRequestHeader(requestheader[0],requestheader[1]);
}
/**
* 遍历路由
*/
for(IResourceUriHandler handler:resourceHandler){
if(!handler.accept(resourceUri)){
continue;
}
handler.handle(resourceUri,httpConntext);
}
} catch (IOException e) {
Log.e("onAcceptRemotePeer",e.toString());
}
}
/**
*路由添加到Set
*/
public void reqisterResourceHandler(IResourceUriHandler iResourceUriHandler){
resourceHandler.add(iResourceUriHandler);
}
}
class StreamToolkit {
/**
*工具类
*/
public static String reabLing(InputStream inputStream) throws IOException {
int c1=0;
int c2=0;
StringBuilder sb=new StringBuilder();
while (c2!=-1&&!(c1=='\r'&&c2=='\n')){
c1=c2;
c2=inputStream.read();
sb.append((char) c2);
}
if(sb.length()==0){
return null;
}
return sb.toString();
}
public static byte[] readRawFromStream(InputStream open) throws IOException {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
byte b[]=new byte[10240];
int nReade;
while((nReade=open.read(b))!=-1){
bos.write(b,0,nReade);
}
return bos.toByteArray();
}
}
public class HttpConntext {
private Socket underlySocke;
private HashMap hashMap;
public HttpConntext(){
this.hashMap=new HashMap<String,String>();
}
public void setUnderlySocke(Socket underlySocke) {
this.underlySocke = underlySocke;
}
public Socket getUnderlySocke(){
return this.underlySocke;
}
public void addRequestHeader(String headerName,String headerValue){
this.hashMap.put(headerName,headerValue);
}
public String getRequstHeaderValue(String headerName){
return (String) this.hashMap.get(headerName);
}
}
public interface IResourceUriHandler { //路由模板
boolean accept(String uri);
void handle(String uri,HttpConntext httpConntext) throws IOException;
}
public class ResourceInAssetsHandler implements IResourceUriHandler {
private Context context;
private String acceptPrefix="/static/";
public ResourceInAssetsHandler(Context context){
this.context=context;
}
@Override
public boolean accept(String uri) {
boolean b=uri.startsWith(acceptPrefix);
Log.e("accept:"+b,acceptPrefix);
return b;
}
@Override
public void handle(String uri, HttpConntext httpConntext) throws IOException {
int startIndex=acceptPrefix.length();
String assetsPath=uri.substring(startIndex);
InputStream open = context.getAssets().open(assetsPath);
byte[] raw=StreamToolkit.readRawFromStream(open);
open.close();
OutputStream outputStream = httpConntext.getUnderlySocke().getOutputStream();
PrintStream printStream=new PrintStream(outputStream);
printStream.println("HTTP/1.1 200 OK");
printStream.println("Content-Length:"+raw.length);
if (assetsPath.endsWith(".html")){
printStream.println("Context-Type:text/html");
}else if(assetsPath.endsWith(".js")){
printStream.println("Context-Type:text/js");
}else if(assetsPath.endsWith(".css")){
printStream.println("Context-Type:text/css");
}else if (assetsPath.endsWith(".jpg")){
printStream.println("Context-Type:text/jpg");
}else if(assetsPath.endsWith(".png")){
printStream.println("Context-Type:text/png");
}
printStream.println();//表示头部数据写完
printStream.write(raw);
printStream.flush();
printStream.close();
}
}
打开App,阅读手记