直接进入主题:本文将会教大家如何实现一个简单的代理服务器(仅支持Http Get),与Android的MediaPlayer结合,从而可以扩展出“播放 防盗链的媒体文件”,“边播放边保存”等的功能。
本文的代码可以到这里下载:http://download.csdn.net/detail/hellogv/4047134,代码分为两个工程:
- J2SE工程:HttpGetProxy,在PC上实现简单的代理服务器,核心类是HttpGetProxy.java,非常容易使用,这里就不唠叨了直接贴出运行效果图:
- Android工程:本文重点,必须唠叨一下。MediaPlayer播放网络音频(http://blog.csdn.net/hellogv/article/details/6406732)与HttpGetProxy.java结合,通过代理服务器播放网络音频。
接下来贴出HttpGetProxy.java的原理图:
接下来贴出HttpGetProxy.java的源码:
通过RemoteSocket的out_remoteSocket可以访问防盗链资源,HttpGetProxy通过2个线程来实现转发,可以在两个线程内实现保存的功能。
- <span style="font-family:Comic Sans MS;font-size:18px;">package com.musicplayer;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetAddress;
- import java.net.InetSocketAddress;
- import java.net.ServerSocket;
- import java.net.Socket;
- import java.net.SocketAddress;
- import java.net.UnknownHostException;
- import android.util.Log;
- public class HttpGetProxy {
- final private String LOCAL_IP_ADDRESS = "127.0.0.1";
- final private int HTTP_PORT = 80;
- private ServerSocket localServer = null;
- private Socket localSocket = null;
- private Socket remoteSocket = null;
- private String remoteIPAddress;
- private InputStream in_remoteSocket;
- private OutputStream out_remoteSocket;
- private InputStream in_localSocket;
- private OutputStream out_localSocket;
- private interface OnFinishListener {
- void onFinishListener();
- }
- public HttpGetProxy(int localport) {
- // --------建立代理中转服务器-----------//
- try {
- localServer = new ServerSocket(localport, 1,
- InetAddress.getByName(LOCAL_IP_ADDRESS));
- } catch (UnknownHostException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /**
- * 结束时,清除所有资源
- */
- private OnFinishListener finishListener =new OnFinishListener(){
- @Override
- public void onFinishListener() {
- System.out.println("..........release all..........");
- Log.e("---->","..........release all..........");
- try {
- in_localSocket.close();
- out_remoteSocket.close();
- in_remoteSocket.close();
- out_localSocket.close();
- localSocket.close();
- remoteSocket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- };
- public void startProxy(String remoteIpAddr) throws IOException {
- remoteIPAddress = remoteIpAddr;
- SocketAddress address = new InetSocketAddress(remoteIPAddress,HTTP_PORT);
- // --------连接目标服务器---------//
- remoteSocket = new Socket();
- remoteSocket.connect(address);
- System.out.println("..........remote Server connected..........");
- Log.e("---->","..........remote Server connected..........");
- in_remoteSocket = remoteSocket.getInputStream();
- out_remoteSocket = remoteSocket.getOutputStream();
- System.out.println("..........init remote Server I/O..........");
- /**
- * 接收本地request,并转发到远程服务器
- */
- new Thread() {
- public void run() {
- int bytes_read;
- byte[] local_request = new byte[5120];
- try {
- // 本地Socket
- localSocket = localServer.accept();
- System.out.println("..........localSocket connected..........");
- Log.e("---->","..........localSocket connected..........");
- in_localSocket = localSocket.getInputStream();
- out_localSocket = localSocket.getOutputStream();
- System.out.println("..........init local Socket I/O..........");
- Log.e("---->","..........init local Socket I/O..........");
- String buffer = "";
- while ((bytes_read = in_localSocket.read(local_request)) != -1) {
- String str = new String(local_request);
- System.out.println("localSocket " + str);
- Log.e("localSocket---->",str);
- buffer = buffer + str;
- if (buffer.contains("GET")
- && buffer.contains("\r\n\r\n")) {
- //---把request中的本地ip改为远程ip---//
- buffer = buffer.replace(LOCAL_IP_ADDRESS,remoteIPAddress);
- System.out.println("已经替换IP");
- out_remoteSocket.write(buffer.getBytes());
- out_remoteSocket.flush();
- continue;
- } else{
- out_remoteSocket.write(buffer.getBytes());
- out_remoteSocket.flush();
- }
- }
- System.out.println("..........local finish receive...........");
- Log.e("---->","..........local finish receive..........");
- finishListener.onFinishListener();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }.start();
- /**
- * 接收远程服务器reply,并转发到本地客户端
- */
- new Thread() {
- public void run() {
- int bytes_read;
- byte[] remote_reply = new byte[5120];
- try {
- System.out.println("..........remote start to receive...........");
- Log.e("---->","..........remote start to receive..........");
- while ((bytes_read = in_remoteSocket.read(remote_reply)) != -1) {
- //System.out.println("remoteSocket " + remote_reply.length);
- //System.out.println("remoteSocket " + new String(remote_reply));
- out_localSocket.write(remote_reply, 0, bytes_read);
- out_localSocket.flush();
- }
- System.out.println("..........remote finish receive...........");
- Log.e("---->","..........remote finish receive..........");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }.start();
- }
- }
- </span>
基础篇实现一个简单的代理服务器与Android的MediaPlayer结合(仅支持Http Get),可以通过代理服务器来转发MediaPlayer的Request以及传输服务器的Response,但基础篇还不能支持Seek,这次提高篇支持了Seek。代理服务器可以增强MediaPlayer对复杂的Http情况的适应,可以播放带防盗链的媒体文件,边播边存,还可以对大体积的媒体文件(如视频)进行多线程预加载,达到快速播放的效果。
本文代码运行在模拟器上,使用Microsoft Network Monitor 3.4来抓包,通过抓包可以发现seek的操作会重新连接服务器,并在Http Get请求中加入Range 字段,所以代理服务器每次监听到MediaPlayer的request都需要新建socket与远程服务器连接。
本文的代码可以到http://download.csdn.net/detail/hellogv/4332362下载,本文程序运行效果如图:
接下来贴出核心代码HttpGetProxy.java:
- public class HttpGetProxy {
- final static private String TAG = "HttpGetProxy";
- final static private String LOCAL_IP_ADDRESS = "127.0.0.1";
- final static private int HTTP_PORT = 80;
- private int local_ip_port;
- private ServerSocket localServer = null;
- private Socket localSocket = null;
- private Socket remoteSocket = null;
- private String remoteHost;
- private InputStream in_remoteSocket;
- private OutputStream out_remoteSocket;
- private InputStream in_localSocket;
- private OutputStream out_localSocket;
- private SocketAddress address;
- private interface OnFinishListener {
- void onFinishListener();
- }
- /**
- * 初始化代理服务器
- * @param localport 代理服务器监听的端口
- */
- public HttpGetProxy(int localport) {
- local_ip_port=localport;
- try {
- localServer = new ServerSocket(localport, 1,
- InetAddress.getByName(LOCAL_IP_ADDRESS));
- } catch (UnknownHostException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /**
- * 结束时,清除所有资源
- */
- private OnFinishListener finishListener = new OnFinishListener() {
- @Override
- public void onFinishListener() {
- System.out.println("..........release all..........");
- Log.e(TAG, "..........release all..........");
- try {
- in_localSocket.close();
- out_remoteSocket.close();
- in_remoteSocket.close();
- out_localSocket.close();
- localSocket.close();
- remoteSocket.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- };
- /**
- * 把网络URL转为本地URL,127.0.0.1替换网络域名
- * @param url 网络URL
- * @return 本地URL
- */
- public String getLocalURL(String url){
- String result = null;
- URI originalURI=URI.create(url);
- remoteHost=originalURI.getHost();
- if(originalURI.getPort()!=-1){//URL带Port
- address = new InetSocketAddress(remoteHost,
- originalURI.getPort());//使用默认端口
- result=url.replace(remoteHost+":"+originalURI.getPort(),
- LOCAL_IP_ADDRESS+":"+local_ip_port);
- }
- else{//URL不带Port
- address = new InetSocketAddress(remoteHost,
- HTTP_PORT);//使用80端口
- result=url.replace(remoteHost,LOCAL_IP_ADDRESS+":"+local_ip_port);
- }
- return result;
- }
- /**
- * 启动代理服务器
- * @throws IOException
- */
- public void startProxy() throws IOException {
- new Thread() {
- public void run() {
- int bytes_read;
- byte[] local_request = new byte[1024];
- byte[] remote_reply = new byte[1024];
- while (true) {
- try {
- //--------------------------------------
- //监听MediaPlayer的请求,MediaPlayer->代理服务器
- //--------------------------------------
- localSocket = localServer.accept();
- Log.e(TAG, "..........localSocket connected..........");
- in_localSocket = localSocket.getInputStream();
- out_localSocket = localSocket.getOutputStream();
- Log.e(TAG, "..........init local Socket I/O..........");
- String buffer = "";//保存MediaPlayer的HTTP请求
- while ((bytes_read = in_localSocket.read(local_request)) != -1) {
- String str = new String(local_request);
- Log.e("localSocket---->", str);
- buffer = buffer + str;
- if (buffer.contains("GET")
- && buffer.contains("\r\n\r\n")) {
- // ---把request中的本地ip改为远程ip---//
- buffer = buffer.replace(LOCAL_IP_ADDRESS,remoteHost);
- break;
- }
- }
- Log.e(TAG, "..........local finish receive..........");
- //--------------------------------------
- //把MediaPlayer的请求发到网络服务器,代理服务器->网络服务器
- //--------------------------------------
- remoteSocket = new Socket();
- remoteSocket.connect(address);
- Log.e(TAG,"..........remote Server connected..........");
- in_remoteSocket = remoteSocket.getInputStream();
- out_remoteSocket = remoteSocket.getOutputStream();
- out_remoteSocket.write(buffer.getBytes());//发送MediaPlayer的请求
- out_remoteSocket.flush();
- //------------------------------------------------------
- //把网络服务器的反馈发到MediaPlayer,网络服务器->代理服务器->MediaPlayer
- //------------------------------------------------------
- Log.e(TAG,"..........remote start to receive..........");
- while ((bytes_read = in_remoteSocket.read(remote_reply)) != -1) {
- out_localSocket.write(remote_reply, 0, bytes_read);
- out_localSocket.flush();
- }
- Log.e(TAG, "..........over..........");
- finishListener.onFinishListener();//释放资源
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }.start();
- }
- }