简单的java版http代理(二)
ort() > -1 url.getPort() : 80);
remote = new Socket(host, port);
InputStream remoteInputStream = remote.getInputStream();
OutputStream remoteOutputStream = remote.getOutputStream();
/**
* 某些服务器对协议头必须一次性读完, 例如QQ空间
* 因此此处先读出协议头, 并且一次写入, 写入之后必须flush
* 否则就跳转到QQ首页了
*/
long contentLength = -1L;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(buffer, 0, buffer.length);
/**
* 读取协议头
* 也可以不读取协议头, 而是直接把inputStream写入到remoteOutputStream
* 为了兼容某些服务器, 此处简单的读取一下协议头
*/
while((buffer = readLine(inputStream)).length > 0)
{
header = new String(buffer, "UTF-8").trim();
if(header.length() < 1)
{
break;
}
if(header.startsWith("Content-Length:"))
{
try
{
contentLength = Long.parseLong(header.substring(15).trim());
}
catch(NumberFormatException e){}
}
bos.write(buffer, 0, buffer.length);
}
/** 协议头和主体之间的空行 */
bos.write(CRLF);
remoteOutputStream.write(bos.toByteArray());
remoteOutputStream.flush();
/** 如果存在contentLength */
if(contentLength > 0)
{
copy(inputStream, remoteOutputStream, 4096, contentLength);
}
try
{
/**
* 将目标主机返回的数据写入到客户端
* 此处应该检查一下Content-Length, 并且根据Content-Length来决定要写入多少数据
* 不过很多服务器经常会不返回Content-Length,
* 没有Content-Length, read函数会一直读取
* 因此使用timeout来解决阻塞的问题
* 超时的时候自动退出线程, 否则该线程就无法释放了
*/
remote.setSoTimeout(10000);
copy(remoteInputStream, outputStream, 4096);
}
catch(SocketTimeoutException e)
{
}
catch(Exception e)
{
e.printStackTrace();
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if(socket != null)
{
socket.close();
}
}
catch(IOException e)
{
}
try
{
if(remote != null)
{
remote.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
public static byte[] readLine(InputStream stream) throws IOException
{
int b = -1;
ByteArrayOutputStream bos = new ByteArrayOutputStream(2048);
while((b = stream.read()) != -1)
{
if(b == '\n')
{
bos.write(b);
break;
}
bos.write(b);
}
return bos.toByteArray();
}
public static void copy(InputStream inputStream, OutputStream outputStream, int bufferSize) throws IOException
{
int length = 0;
byte