package com.bigdo.service; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.net.URLConnection; import java.util.ArrayList; import com.bigdo.common.BDSQLiteHelper; import com.bigdo.common.RConfig; import com.bigdo.common.RState; import android.os.Bundle; import android.os.Environment; import android.util.Log; public class WebServer extends Thread { int port = 0; ServerSocket serverSocket = null; boolean isLoop = false; VideoPayService PayService; String baseDir = ""; public WebServer(VideoPayService PayService) { super(); BDSQLiteHelper sqlobj = null; this.PayService = PayService; } @Override public void run() { super.run(); String status = Environment.getExternalStorageState(); if (status.equals(Environment.MEDIA_MOUNTED)) { baseDir = Environment.getExternalStorageDirectory() + RConfig.Video_Dir; startService(); } } public void startService() { BDSQLiteHelper sqlobj = null; while (!this.isInterrupted() && serverSocket == null) { try { this.port = 0; isLoop = false; int port = 57030; try { // 创建服务器套接字 serverSocket = new ServerSocket(port); } catch (Exception e) { try { if (serverSocket != null) { serverSocket.close(); } } catch (Exception e1) { } serverSocket = null; port = 0; sendStatusMsg(RState.Video_Status_Init_Error); continue; } this.port = 0; if (serverSocket != null) { try { this.port = serverSocket.getLocalPort(); } catch (Exception e) { this.port = 0; } } isLoop = true; sendStatusMsg(RState.Video_Status_Run); while (isLoop && !this.isInterrupted()) { // 接收客户端套接字 Socket socket = serverSocket.accept(); RecvThread t = new RecvThread(socket); // t.setDaemon(true);// 设为守护线程 t.start(); } } catch (Exception e) { isLoop = false; sendStatusMsg(RState.Video_Status_Close); } finally { try { if (serverSocket != null) { serverSocket.close(); } } catch (IOException e) { } serverSocket = null; } } sendStatusMsg(RState.Video_Status_Run); } public void sendStatusMsg() { int port = 0; if (serverSocket != null) { try { port = serverSocket.getLocalPort(); } catch (Exception e) { } } Bundle data = new Bundle(); data.putInt("status", isLoop ? RState.Video_Status_Run : RState.Video_Status_Unknown); data.putInt("prot", port); PayService.sendBroadcastMsg(RState.Video_Status_Info, "服务状态", data); } public void sendStatusMsg(int status) { int port = 0; if (serverSocket != null) { try { port = serverSocket.getLocalPort(); } catch (Exception e) { } } Bundle data = new Bundle(); data.putInt("status", status); data.putInt("prot", port); PayService.sendBroadcastMsg(RState.Video_Status_Info, "服务状态", data); } public void stopService() { isLoop = false; try { if (serverSocket != null) { serverSocket.close(); } } catch (Exception e) { } serverSocket = null; interrupt(); sendStatusMsg(RState.Video_Status_Close); } private class RecvThread extends Thread { Socket socket; public RecvThread(Socket socket) { this.socket = socket; } @Override public void run() { super.run(); handler(); } private void handler() { BDSQLiteHelper sqlobj = null; if (socket != null) { InputStream in = null; try { byte[] data = new byte[1024 * 4]; int rc = 0; StringBuffer r_sb = new StringBuffer(); in = socket.getInputStream(); while (!this.isInterrupted() && (socket != null && (!socket.isClosed() && socket .isConnected()) && (rc = in .read(data)) != -1)) { if (rc > 0) { r_sb.append(new String(data, 0, rc, "UTF-8")); ArrayList<String> rs_item = analysisHttp(r_sb); String con = "close"; for (int i = 0; i < rs_item.size(); i++) { HttpEntity entity = analysisHttpEntity(rs_item .get(i)); if (entity != null) { con = entity.con; outFile(entity); } } if ("close".equals(con)) { closeSocket(); data = null; break; } } } } catch (Exception e) { // Log.e("entity_error", e.getMessage()); } finally { try { if (in != null) { in.close(); } } catch (Exception e) { } closeSocket(); } } } private void closeSocket() { try { if (socket != null) { socket.shutdownInput(); socket.shutdownOutput(); socket.close(); } } catch (Exception e) { } socket = null; interrupt(); } private void outFile(HttpEntity entity) { BDSQLiteHelper sqlobj = null; if (socket != null) { OutputStream out = null; try { out = socket.getOutputStream(); } catch (IOException e4) { } if (out != null) { String e = "\r\n"; if (entity != null && entity.File != null && !entity.File.equals("")) { try { // String path = "/sdcard/1.mp4"; File fd = new File(baseDir); Log.e("out-file", baseDir + entity.File + ".r"); File f = new File(fd, entity.File + ".r"); int size = 0; if (f.exists()) { FileInputStream in = null; try { long flg = f.length(); in = new FileInputStream(f); String http_code = "206 Partial Content"; if (entity.Range_e <= 0) { entity.Range_e = flg; } long rlg = (entity.Range_e - entity.Range_s); if (entity.Range_s == 0) { http_code = "200 OK"; rlg = flg; } StringBuilder header = new StringBuilder(); header.append(("HTTP/1.1 " + http_code + e)); header.append(("Connection: close" + e)); // header.append(("Content-Type: video/mp4" // + e)); String contentType = VideoMime.Mime(f .getName()); header.append(("Content-Type: " + contentType + e)); Log.e("Content-Type" + contentType, ""); header.append(("Accept-Ranges: bytes" + e)); if (entity.Range_s > 0) { header.append(("Content-Range: bytes " + entity.Range_s + "-" + entity.Range_e + "/" + flg + e)); } header.append(("Content-Length: " + rlg + e + e)); in.skip(entity.Range_s + 180); out.write(header.toString().getBytes()); header.delete(0, header.length()); int t_read_count = 0; int blg = 1024 * 4; if (rlg < blg) { blg = (int) rlg; } byte[] buffer = new byte[blg]; while ((!socket.isClosed() && socket .isConnected()) && (size = in.read(buffer)) != -1) { t_read_count += size; out.write(buffer, 0, size); out.flush(); if (t_read_count >= rlg) { break; } } } catch (Exception e1) { // Log.e("outf", // "error-rFile: " + e1.getMessage(), e1); } finally { try { if (in != null) { in.close(); } } catch (Exception e2) { } in = null; } } } catch (Exception e3) { } } } } } }; private class HttpEntity { public String File = ""; public long Range_s = 0; public long Range_e = 0; public String con = ""; } private ArrayList<String> analysisHttp(StringBuffer sb) { BDSQLiteHelper sqlobj = null; ArrayList<String> rs_item = new ArrayList<String>(); int lg = sb.length(); String el = "\r\n"; String http1_1 = " HTTP/1.1" + el, http1_0 = " HTTP/1.0" + el; while (lg > 0) { if (lg > 0) { int s = sb.indexOf("GET "); if (s < 0) { sb.delete(0, lg); return rs_item; } int http_s = sb.indexOf(http1_1); if (http_s < 0) { http_s = sb.indexOf(http1_0); } int es = sb.indexOf(el); if (http_s > s && http_s + http1_1.length() == es + el.length()) { int s_n = sb.indexOf(el + el + "GET ", es); if (s_n < es) { s_n = lg; } rs_item.add(sb.substring(s, s_n)); sb.delete(s, s_n); } else { return rs_item; } lg = sb.length(); } } return rs_item; } private HttpEntity analysisHttpEntity(final String src) { BDSQLiteHelper sqlobj = null; HttpEntity entity = new HttpEntity(); if (src != null && !src.equals("")) { String el = "\r\n", get = "GET "; String http1_1 = " HTTP/1.1" + el, http1_0 = " HTTP/1.0" + el; int s = src.indexOf(get) + get.length(), e = src.indexOf(http1_1); if (e < 0) { e = src.indexOf(http1_0, s); } if (e > 0) { entity.File = src.substring(s, e); } String Range = "Range: bytes="; s = src.indexOf(Range, e + http1_1.length()); if (s > 0) { s += Range.length(); e = src.indexOf(el, s); if (e > 0) { String Range_s_e = src.substring(s, e); if (Range_s_e != null && !Range_s_e.equals("")) { String[] r_s_to_e = Range_s_e.split("[\\-]"); if (r_s_to_e != null && r_s_to_e.length > 0) { if (r_s_to_e[0] != null && !r_s_to_e[0].equals("")) { entity.Range_s = Integer.parseInt(r_s_to_e[0]); } if (r_s_to_e.length > 1 && r_s_to_e[1] != null && !r_s_to_e[1].equals("")) { entity.Range_e = Integer.parseInt(r_s_to_e[1]); } } } } } String con = "Connection: "; s = src.indexOf(con); if (s > 0) { s += con.length(); e = src.indexOf(el, s); if (e > 0) { entity.con = src.substring(s, e); } } } // if (entity.Range_e < entity.Range_s) { // entity.Range_e += entity.Range_s + 1024 * 1024 * 1; // } return entity; } }