搜索时StreamProxy错误

时间:2014-08-12 19:44:49

标签: android proxy streaming android-videoview

我使用StreamProxy类来传输来自互联网的视频,但是当我寻找视频播放器时,我会收到一个"连接由同行重置"错误,视频停止。

你知道我该怎么办呢?

我找到了libMedia(http://libeasy.alwaysdata.net/)的解决方案,但我想实现自己的解决方案。

public class StreamProxy implements Runnable {
    private static final String LOG_TAG = StreamProxy.class.getName();

    private int port = 12012;

    public int getPort() {
        return port;
    }

private boolean isRunning = true;
private ServerSocket socket;
private Thread thread;

public void init() {
    try {
        socket = new ServerSocket(port, 0, InetAddress.getByAddress(new byte[] {127, 0, 0, 1}));
        socket.setSoTimeout(5000);
        port = socket.getLocalPort();
        Log.d(LOG_TAG, "port " + port + " obtained");
    } catch (UnknownHostException e) {
        Log.e(LOG_TAG, "Error initializing server", e);
    } catch (IOException e) {
        Log.e(LOG_TAG, "Error initializing server", e);
    }
}

public void start() {

    if (socket == null) {
        throw new IllegalStateException("Cannot start proxy; it has not been initialized.");
    }

    thread = new Thread(this);
    thread.start();
}

public void stop() {
    isRunning = false;

    if (thread == null) {
        throw new IllegalStateException("Cannot stop proxy; it has not been started.");
    }

    thread.interrupt();
    try {
        thread.join(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    Log.d(LOG_TAG, "running");
    while (isRunning) {
        try {
            Socket client = socket.accept();
            if (client == null) {
                continue;
            }
            Log.d(LOG_TAG, "client connected");
            HttpRequest request = readRequest(client);
            processRequest(request, client);
        } catch (SocketTimeoutException e) {
            // Do nothing
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error connecting to client", e);
        }
    }
    Log.d(LOG_TAG, "Proxy interrupted. Shutting down.");
}

private HttpRequest readRequest(Socket client) {
    HttpRequest request = null;
    InputStream is;
    String firstLine;
    try {
        is = client.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8192);
        firstLine = reader.readLine();
    } catch (IOException e) {
        Log.e(LOG_TAG, "Error parsing request", e);
        return request;
    }

    if (firstLine == null) {
        Log.i(LOG_TAG, "Proxy client closed connection without a request.");
        return request;
    }

    StringTokenizer st = new StringTokenizer(firstLine);
    String method = st.nextToken();
    String uri = st.nextToken();
    Log.d(LOG_TAG, uri);
    String realUri = uri.substring(1);
    Log.d(LOG_TAG, realUri);
    request = new BasicHttpRequest(method, realUri);
    return request;
}

private HttpResponse download(String url) {
    DefaultHttpClient seed = new DefaultHttpClient();
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    SingleClientConnManager mgr = new MyClientConnManager(seed.getParams(), registry);
    DefaultHttpClient http = new DefaultHttpClient(mgr, seed.getParams());
    HttpGet method = new HttpGet(url);
    HttpResponse response = null;
    try {
        Log.d(LOG_TAG, "starting download");
        response = http.execute(method);
        Log.d(LOG_TAG, "downloaded");
    } catch (ClientProtocolException e) {
        Log.e(LOG_TAG, "Error downloading", e);
    } catch (IOException e) {
        Log.e(LOG_TAG, "Error downloading", e);
    }
    return response;
}

private void processRequest(HttpRequest request, Socket client) throws IllegalStateException, IOException {
    if (request == null) {
        return;
    }
    Log.d(LOG_TAG, "processing");
    String url = request.getRequestLine().getUri();
    HttpResponse realResponse = download(url);
    if (realResponse == null) {
        return;
    }

    Log.d(LOG_TAG, "downloading...");

    InputStream data = realResponse.getEntity().getContent();
    StatusLine line = realResponse.getStatusLine();
    HttpResponse response = new BasicHttpResponse(line);
    response.setHeaders(realResponse.getAllHeaders());

    Log.d(LOG_TAG, "reading headers");
    StringBuilder httpString = new StringBuilder();
    httpString.append(response.getStatusLine().toString());

    httpString.append("\n");
    for (Header h : response.getAllHeaders()) {
        httpString.append(h.getName()).append(": ").append(h.getValue()).append("\n");
    }
    httpString.append("\n");
    Log.d(LOG_TAG, "headers done");

    try {
        byte[] buffer = httpString.toString().getBytes();
        int readBytes;
        Log.d(LOG_TAG, "writing to client");
        client.getOutputStream().write(buffer, 0, buffer.length);

        // Start streaming content.
        byte[] buff = new byte[1024 * 50];
        while (isRunning && (readBytes = data.read(buff, 0, buff.length)) != -1) {
            client.getOutputStream().write(buff, 0, readBytes);
        }
    } catch (Exception e) {
        Log.e("", e.getMessage(), e);
    } finally {
        if (data != null) {
            data.close();
        }
        client.close();
    }
}

private class IcyLineParser extends BasicLineParser {
    private static final String ICY_PROTOCOL_NAME = "ICY";

    private IcyLineParser() {
        super();
    }

    @Override
    public boolean hasProtocolVersion(CharArrayBuffer buffer, ParserCursor cursor) {
        boolean superFound = super.hasProtocolVersion(buffer, cursor);
        if (superFound) {
            return true;
        }
        int index = cursor.getPos();

        final int protolength = ICY_PROTOCOL_NAME.length();

        if (buffer.length() < protolength)
            return false; // not long enough for "HTTP/1.1"

        if (index < 0) {
            // end of line, no tolerance for trailing whitespace
            // this works only for single-digit major and minor version
            index = buffer.length() - protolength;
        } else if (index == 0) {
            // beginning of line, tolerate leading whitespace
            while ((index < buffer.length()) && HTTP.isWhitespace(buffer.charAt(index))) {
                index++;
            }
        } // else within line, don't tolerate whitespace

        return index + protolength <= buffer.length() && buffer.substring(index, index + protolength).equals(ICY_PROTOCOL_NAME);

    }

    @Override
    public ProtocolVersion parseProtocolVersion(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException {

        if (buffer == null) {
            throw new IllegalArgumentException("Char array buffer may not be null");
        }
        if (cursor == null) {
            throw new IllegalArgumentException("Parser cursor may not be null");
        }

        final int protolength = ICY_PROTOCOL_NAME.length();

        int indexFrom = cursor.getPos();
        int indexTo = cursor.getUpperBound();

        skipWhitespace(buffer, cursor);

        int i = cursor.getPos();

        // long enough for "HTTP/1.1"?
        if (i + protolength + 4 > indexTo) {
            throw new ParseException("Not a valid protocol version: " + buffer.substring(indexFrom, indexTo));
        }

        // check the protocol name and slash
        if (!buffer.substring(i, i + protolength).equals(ICY_PROTOCOL_NAME)) {
            return super.parseProtocolVersion(buffer, cursor);
        }

        cursor.updatePos(i + protolength);

        return createProtocolVersion(1, 0);
    }

    @Override
    public StatusLine parseStatusLine(CharArrayBuffer buffer, ParserCursor cursor) throws ParseException {
        return super.parseStatusLine(buffer, cursor);
    }
}

class MyClientConnection extends DefaultClientConnection {
    @Override
    protected HttpMessageParser createResponseParser(final SessionInputBuffer buffer, final HttpResponseFactory responseFactory, final HttpParams params) {
        return new DefaultResponseParser(buffer, new IcyLineParser(), responseFactory, params);
    }
}

class MyClientConnectionOperator extends DefaultClientConnectionOperator {
    public MyClientConnectionOperator(final SchemeRegistry sr) {
        super(sr);
    }

    @Override
    public OperatedClientConnection createConnection() {
        return new MyClientConnection();
    }
}

class MyClientConnManager extends SingleClientConnManager {
    private MyClientConnManager(HttpParams params, SchemeRegistry schreg) {
        super(params, schreg);
    }

    @Override
    protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry sr) {
        return new MyClientConnectionOperator(sr);
    }
}

}

0 个答案:

没有答案