选择显示字体大小

用socket类实现http协议客户端应用

出自:www.cn-java.com

http客户端程序已集成在java语言中,可以通过urlconnection类调用。遗憾的
是,由于sun没有公布http客户程序的源码,它实现的细节仍是一个谜。本文根据http
协议规范,用java.net.socket类实现一个http协议客户端程序。

1.socket类:
了解tcp/ip协议集通信的读者知道,协议间的通信是通过socket完成的。在
java.net包中,socket类就是对socket的具体实现。它通过连接到主机后,返回一个
i/o流,实现协议间的信息交换。

2 . http协议
http协议同其它tcp/ip协议集中的协议一样,是遵循客户/服务器模型工作的。客
户端发往服务端的信息格式如下:
------------------------------
请求方法 url http协议的版本号
提交的元信息
**空行**
实体
------------------------------
请求方法是对这次连接工作的说明,目前http协议已经发展到1.1版,它包括get、
head、post、delete、options、trace、put七种。元信息是关于当前请求的信息。通
过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元
信息的引入使http协议通信更加稳妥可靠。实体是请求的具体内容。
将上述报文发往web服务器,如果成功,应答格式如下:
--------------------------------
http协议的版本号 应答状态码 应答状态码说明
接收的元信息
**空行**
实体
--------------------------------
以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。
下面用最常用的get方法,来说明具体的报文应用
----------------------------------
get http://www.youhost.com http/1.0
accept: www/source; text/html; image/gif; image/jpeg; */*
user_agent: myagent
**空行**
-----------------------------------
这个报文是向www.youhost.com主机请求一个缺省html文档。客户端http协议版本
号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分
隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码:
------------------------------------
http/1.1 200 ok
date: tue, 14 sep 1999 02:19:57 gmt
server: apache/1.2.6
connection: close
content-type: text/html
**空行**
......
------------------------------------
http/1.1表示这个http服务器是1.1版,200是服务器对客户请求的应答状态码,ok
是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元
信息的解释请参阅.net.net标准草案:rfc2616)。

3. http客户端程序:

import java.net.*;
import java.io.*;
import java.util.properties;
import java.util.enumeration;
public class http {
protected socket client;
protected bufferedoutputstream sender;
protected bufferedinputstream receiver;
protected bytearrayinputstream bytestream;
protected url target;
private int responsecode=-1;
private string responsemessage="";
private string serverversion="";
private properties header = new properties();
public http() { }
public http(string url) {
get(url) ;
}
/* get方法根据url,会请求文件、数据库查询结果、程序运行结果等多种内容 */
public void get(string url) {
try {
checkhttp(url);
openserver(target.gethost(),target.getport() );
string cmd = "get "+ geturlformat(target) +" http/1.0\r\n"
+ getbaseheads()+"\r\n";
sendmessage(cmd);
receivemessage();
}catch(protocolexception p) {
p.printstacktrace();
return;
}catch(unknownhostexception e) {
e.printstacktrace();
return;
}catch(ioexception i)

i.printstacktrace();
return;
}
}

/*
* head方法只请求url的元信息,不包括url本身。若怀疑本机和服务器上的
* 文件相同,用这个方法检查最快捷有效。
*/
public void head(string url) {
try {
checkhttp(url);
openserver(target.gethost(),target.getport() );
string cmd = "head "+geturlformat(target)+" http/1.0\r\n"
+getbaseheads()+"\r\n";
sendmessage(cmd);
receivemessage();
}catch(protocolexception p) {
p.printstacktrace();
return;
}catch(unknownhostexception e) {
e.printstacktrace();
return;
}catch(ioexception i)

i.printstacktrace();
return;
}
}
/*
* post方法是向服务器传送数据,以便服务器做出相应的处理。例如网页上常用的
* 提交表格。
*/
public void post(string url,string content) {
try {
checkhttp(url);
openserver(target.gethost(),target.getport() );
string cmd = "post "+ geturlformat(target) +"
http/1.0\r\n"+getbaseheads();
cmd += "content-type: application/x-www-form-urlencoded\r\n";
cmd += "content-length: " + content.length() + "\r\n\r\n";
cmd += content+"\r\n";
sendmessage(cmd);
receivemessage();
}catch(protocolexception p) {
p.printstacktrace();
return;
}catch(unknownhostexception e) {
e.printstacktrace();
return;
}catch(ioexception i)

i.printstacktrace();
return;
}

}
protected void checkhttp(string url) throws protocolexception {
try {
url target = new url(url);
if(target==null !target.getprotocol().touppercase().equals("http") )
throw new protocolexception("这不是http协议");
this.target = target;
}catch(malformedurlexception m) {
throw new protocolexception("协议格式错误");
}
}
/*
* 与web服务器连接。若找不到web服务器.netaddress会引发unknownhostexception
* 异常。若socket连接失败,会引发ioexception异常。
*/
protected void openserver(string host,int port) throws
unknownhostexception,ioexception {
header.clear();
responsemessage=""; responsecode=-1;
try {
if(client!=null) closeserver();
if(bytestream != null) {
bytestream.close(); bytestream=null;
}
.netaddress address = .netaddress.getbyname(host);
client = new socket(address,port==-1?80:port);
sender = new bufferedoutputstream(client.getoutputstream());
receiver = new bufferedinputstream(client.getinputstream());
}catch(unknownhostexception u) {
throw u;
}catch(ioexception i) {
throw i;
}
}
/* 关闭与web服务器的连接 */
protected void closeserver() throws ioexception {
if(client==null) return;
try {
client.close(); sender.close(); receiver.close();
}catch(ioexception i) {
throw i;
}
client=null; sender=null; receiver=null;
}
protected string geturlformat(url target) {
string spec = "http://"+target.gethost();
if(target.getport()!=-1)
spec+=":"+target.getport();
return spec+=target.getfile();
}

/* 向web服务器传送数据 */
protected void sendmessage(string data) throws ioexception{
sender.write(data.getbytes(),0,data.length());
sender.flush();
}
/* 接收来自web服务器的数据 */
protected void receivemessage() throws ioexception{
byte data[] = new byte[1024];
int count=0;
int word=-1;
// 解析第一行
while( (word=receiver.read())!=-1 ) {
if(word=='\r'word=='\n') {
word=receiver.read();
if(word=='\n') word=receiver.read();
break;
}
if(count == data.length) data = addcapacity(data);
data[count++]=(byte)word;
}
string message = new string(data,0,count);
int mark = message.indexof(32);
serverversion = message.substring(0,mark);
while( mark responsecode = integer.parseint(message.substring(mark+1,mark+=4));
responsemessage = message.substring(mark,message.length()).trim();

// 应答状态码和处理请读者添加
switch(responsecode) {
case 400:
throw new ioexception("错误请求");
case 404:
throw new filenotfoundexception( geturlformat(target) );
case 503:
throw new ioexception("服务器不可用" );
}
if(word==-1) throw new protocolexception("信息接收异常终止");
int symbol=-1;
count=0;
// 解析元信息
while( word!='\r' && word!='\n' && word>-1) {
if(word=='\t') word=32;
if(count==data.length) data = addcapacity(data);
data[count++] = (byte)word;
parseline: {
while( (symbol=receiver.read()) >-1 ) {
switch(symbol) {
case '\t':
symbol=32; break;
case '\r':
case '\n':
word = receiver.read();
if( symbol=='\r' && word=='\n') {
word=receiver.read();
if(word=='\r') word=receiver.read();
}
if( word=='\r' word=='\n' word>32) break parseline;
symbol=32; break;
}
if(count==data.length) data = addcapacity(data);
data[count++] = (byte)symbol;
}
word=-1;
}
message = new string(data,0,count);
mark = message.indexof(':');
string key = null;
if(mark>0) key = message.substring(0,mark);
mark++;
while( mark string value = message.substring(mark,message.length() );
header.put(key,value);
count=0;
}
// 获得正文数据
while( (word=receiver
if(count>0) bytestream = new bytearrayinputstream(data,0,count);
data=null;
closeserver();
}
public string getresponsemessage() {
return responsemessage;
}
public int getresponsecode() {
return responsecode;
}
public string getserverversion() {
return serverversion;
}
public inputstream getinputstream() {
return bytestream;
}
public synchronized string getheaderkey(int i) {
if(i>=header.size()) return null;
enumeration enum = header.propertynames();
string key = null;
for(int j=0; j<=i; j++)
key = (string)enum.nextelement();
return key;
}
public synchronized string getheadervalue(int i) {
if(i>=header.size()) return null;
return header.getproperty(getheaderkey(i));
}
public synchronized string getheadervalue(string key) {
return header.getproperty(key);
}
protected string getbaseheads() {
string inf = &quot;user-agent: myselfhttp/1.0\r\n&quot;+
&quot;accept: www/source; text/html; image/gif; */*\r\n&quot;;
return inf;
}
private byte[] addcapacity(byte rece[]){
byte temp[] = new byte[rece.length+1024];
system.arraycopy(rece,0,temp,0,rece.length);
return temp;
}
}

注: 程序中只实现get、head、post三种方法。其他几种因不常使用,暂且忽略。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons