近来好多人亮相自已发出HTTP请求,我也正好也在做HTTP代理,还可以看看我写的一个文章也有关于HttpClient的内容
http://feixing2008.iteye.com/blog/569927
其中我没有使用HttpClient这个东西,我想更直接地透传数据。下边写了几个工具方法,引出内容。还有出遇到的一些问题。
public static byte[] getDataByInputStream(InputStream in)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[BUF_SIZE];
int len = 0;
while ((len = in.read(b, 0, BUF_SIZE)) != -1) {
baos.write(b, 0, len);
}
baos.flush();
byte[] bytes = baos.toByteArray();
return bytes;
}
上边的方法是从流中取出所有数据,放在数组中。BUF_SIZE常量自已设定,意义为缓冲区的大小。
在以上的基础上加增多一个方法
public static String getStrByInputStream(InputStream in, String outEncode) throws IOException{
byte[] btyStr = getDataByInputStream(in);
String str = new String(btyStr, outEncode);
return str;
}
这个方法主要是将响应的数据转成字符串。其中outEncode是字符器的编码。这里我要说一个问题
就是Content-Length这个头的主要含义是上边btye[]的长度,而不是String的length()的长度。
Content-Length反映了字节流的长度,这个受操作系统编码的影响。所以需要得到响应的编码形式。
继续再看看这个方法。
public static String getStrEveryLine(InputStream in, String encode)
throws IOException {
StringBuilder rs = new StringBuilder();
Scanner inScn = new Scanner(in);
String buf = "";
while(inScn.hasNextLine()){
buf = inScn.nextLine();
if(buf.length() < 1){
rs.append("\r\n");
break;
}
rs.append(buf);
rs.append("\r\n");
}
return rs.toString();
这个方法是是通过Scanner来处理流数据。本来使用getStrByInputStream这个方法好像已满足需求,其实非也,因为出现一个问题。
问题:
浏览器发出请求时,在完成请求头后关不会将socket关闭的,也就是说
in.read()是不会返回-1,只是线程会一直阻塞在那里。
再具体一点就是这样
GET / HTTP/1.0
Host: www.taobao.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.0.11) Gecko/2009060308 Ubuntu/9.04 (jaunty) Firefox/3.0.11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: text/html
Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: t=31d7b3ed1734e98759c7009c7cc5d492; cna=G2ZHBE1o0hUCATjEb3H2nl0g
<---------这里有个空行,读完这个空行再读的话会阻塞。所以读到这个空间就要跳出,不要再read
在请求头遇到这个情况还算好,因为可以通过一个空行可以发现头已经结束。
PS:不过这里还有个问题,如果是POST的话,在这个空行后边还是会有参数请求,这个时间就需要处理。然而我还没有实现。
在响应接收也是存在这个情况,这个问题更麻烦,因为是在响应数据流中读完一个字节流后阻塞,一般服务器是不会马上关闭Socket的,因为它不知你什么时间关闭,一般是等到10秒后才关闭。天吖,这个很影响我代理的性能。
其中一个解决方法是得到响应头的中Content-Length,再一次说明,这个头的值指的是字节流大小, 不是字符串大小。有了这个大小便可以根据大小读数据,知道何时数据已经完整,而不需要等服务器来关闭连接。
然而有时服务器是不会传Content-Length这个值。我也没有什么好方法,给合我代理的功能,我直接将流指向真实客服端的输出流当中。
BufferedInputStream bufIn = new BufferedInputStream(in);
ArrayList<Byte> bys = new ArrayList<Byte>();
BufferedOutputStream outBuf = new BufferedOutputStream(outToClient);
int c = 0;
int cCnt = 0;
while(( c = bufIn.read()) != -1){
++cCnt;
byte bc = (byte)c;
bys.add(bc);
outBuf.write(c);
if((cCnt % 256) == 0){
outBuf.flush();
}
}
outBuf.close();
这代码比较笨拙,其实不用细看,只是说明直接输到真实的客户端的输出流中。这个效率大大提升。
其中还有一个地方是线程池,这个是我需要改进的另一块,继续关注HTTP协议的相关开发。
分享到:
相关推荐
在Java中编写HTTP代理,主要涉及以下几个核心概念: 1. **Socket编程**:Java的Socket类提供了在网络中进行通信的基本功能。代理服务器会创建一个监听套接字,等待客户端的连接请求。一旦客户端连接,服务器端就会...
使用这样的工具可以提高开发效率,减少手动编写代理类的时间,同时也降低了错误的可能性。然而,需要注意的是,随着WCF、WF、WPF等技术的出现,以及现在更流行的RESTful API,ASMX类型的WebService在现代开发中的...
`AopTargetUtils`是Spring AOP模块中的一个辅助类,它提供了若干静态方法来帮助开发者获取代理对象的真实目标对象。这个工具类主要服务于以下两种情况: 1. **JDK动态代理**:当我们的代理对象是由Spring的...
Web服务代理类是C#中访问Web服务的关键组件,它允许开发者通过调用本地对象的方法来与远程Web服务通信。本篇文章将详细介绍"C# 代理类生成工具"及其在Visual Studio(VS)中的应用。 1. **Web服务代理类**:Web服务...
局部,全局,代理,Sockts5,易语言源码,可以用易语言编译,局部代理和全局代理。
这个工具箱提供了这些算法的实现,使得用户无需从头编写代码,就能应用到自己的项目中。`RBF-Radial-Basis-Function-Network-master.zip` 文件可能包含了一个RBF网络的具体实现,而`SurrogateOptimizationModule_...
例如在`StaticProxyPayServiceImpl`类中,它实现了`PayService`接口,并持有了真实的`PayService`对象,当调用`callback`和`save`方法时,会在调用前后添加一些额外的打印语句,这就是静态代理的增强功能。...
一个c语言编写的sock5代理工具
在本项目中,开发者使用了QT库和C++编程语言创建了一个HTTP服务器,该服务器具有HTTP代理的功能。这个实现涉及到了多个核心组件和概念,包括网络通信、HTTP协议解析、代理服务以及配置管理等。以下是对这些关键知识...
总结起来,通过手动编写代理类实现WCF通信提供了更多的灵活性,而远程开关机技术则展示了网络编程在实际应用中的潜力。掌握这些技能有助于开发者在没有现成工具时也能创建高效、可靠的分布式系统。
“源码”标签暗示了这篇博文可能包含或涉及HTTP代理的源代码实现,可能是用某种编程语言(如Java、Python、C#等)编写的。源代码可以帮助读者理解代理服务器的工作原理,或者提供一个可自定义的代理服务器实现。 ...
gost - Go语言编写多功能网络代理转发工具.zip
3. **分析工具的实现**:用户代理分析工具通常会包含一系列的正则表达式和条件判断,用于从用户代理字符串中提取关键信息。例如,通过匹配"Firefox"、"Chrome"、"Safari"等关键词,工具可以确定用户使用的浏览器类型...
GoProxyPool是一款开源的基于Golang语言编写的代理池工具,可以自动化地获取、验证和维护可用的HTTP、HTTPS和SOCKS5代理,为应用程序提供高质量的代理服务。 GoProxyPool使用简单,可以通过配置文件或命令行参数来...
IE代理设置工具,VC编写,需要源码给我发邮件。
在实际应用中,代理IP获取工具通常会通过网络爬虫技术自动收集网络上的免费或付费代理IP,并对这些IP进行有效性验证,确保它们可以正常工作。C#中的HttpWebRequest、HttpClient等类库可以帮助开发者实现网络请求,而...
【简单HTTP代理服务器】是一种网络通信工具,它允许用户通过该服务器作为中介,与互联网上的其他服务器进行交互。这样的设计可以用于多种目的,包括隐私保护、网络访问控制、负载均衡等。在这里,我们讨论的是一个自...
总结,WebService作为跨平台的通信手段,其编写、调用和测试是IT开发中的重要技能。理解WSDL、SOAP、UDDI等核心技术,掌握相应的开发工具和测试方法,对于提升系统集成和数据交换的能力至关重要。同时,不断学习和...
在Lotus Domino中,代理是一种强大的工具,用于自动化工作流程、处理数据和响应用户请求。标题提到的"domino中的代理"主要涉及LotusScript编写的两种类型:Web代理和Notes代理。这两种代理在许多方面有共同之处,但...
在这个“ASP编写的局域网内Web QQ通信工具”中,我们可以推断出该工具是利用ASP技术来实现的,它能够在局域网内部署,让网络内的用户无需通过互联网就能进行QQ聊天。 首先,我们需要理解ASP的工作原理。当用户在...