http编程java_Java网络编程:实现HTTP模拟器

在讨论HTTP协议的具体请求和响应头字段之前,让我们先来利用以前所学的知识来实现一个HTTP模拟器。所谓HTTP模拟器就是可以在用户输入HTTP 的请求消息后,由这个模拟器将HTTP请求发送给相应的服务器,再接收服务器的响应消息。这个HTTP模拟器有几下特点:

1.  可以手工输入HTTP请求,并向服务器发送。

2.  接收服务器的响应消息。

3.  消息头和实体内容分段显示,也就是说,并不是象Telnet等客户端一样将HTTP响

应消息全部显示,而是先显示消息头,然后由用户决定是否显示实体内容。

4.  集中发送请求。这个HTTP模拟器和Telnet不同的是,并不是一开始就连接服务器,

而是将域名、端口以及HTTP请求消息都输完后,才连接服务器,并将这些请求发送给服务器。这样做的可以预防服务器提前关闭网络连接的现象。

5.可以循环做上述的操作。

从以上的描述看,要实现这个HTTP模拟器需要以下五步:

1.  建立一个大循环,在循环内部是一个请求/响应对。这样就可以向服务器发送多次请求/响应以了。下面的四步都是被包括在循环内部的。

2.  从控制台读取域名和端口,这个功能可以由readHostAndPort(...)来完成。

3.  从控制台读取HTTP请求消息,这个功能由readHttpRequest(...)来完成。

4.  向服务器发送HTTP请求消息,这个功能由sendHttpRequest()来完成。

5.  读取服务器回送的HTTP响应消息,这个功能由readHttpResponse(...)来完成。

下面我们就来逐步实现这五步:

一、建立一个大循环

在建立这个循环之前,先建立一个中叫HttpSimulator的类,并在这个类中定义一个run方法用来运行这个程序。实现代码如下:

001packagehttp;002003importjava.net.*;004importjava.io.*;005006publicclassHttpSimulator007{008privateSocket socket;009privateintport=80;010privateString host="localhost";011privateString request="";//HTTP请求消息012privatebooleanisPost, isHead;0139b8a8a44dd1c74ae49c20a7cd451974e.png 9b8a8a44dd1c74ae49c20a7cd451974e.png014publicvoidrun()throwsException015{016BufferedReader reader=newBufferedReader(newInputStreamReader(017System.in));018while(true)//开始大循环019{020try021{022if(!readHostAndPort(reader))023break;024readHttpRequest(reader);025sendHttpRequest();026readHttpResponse(reader);027}028catch(Exception e)029{030System.out.println("err:"+e.getMessage());031}032}033}034publicstaticvoidmain(String[] args)throwsException035{036newHttpSimulator().run();037}038}

从上面的代码可以看出, 第022、024、025和026分别调用了上述的四个方法。这些方法的具体实现将在后面讨论。上面的代码除了调用这四个核心方法外,还做了一些准备工 作。在008至012行定义了一些以后要用到的变量。在016和017行使用控制台的输入流建立了BufferedReader对象,通过这个对象,可以 直接从控制台读取字符串,而不是一个个地字节。

二、readHostAndPort(...)方法的实现

这个方法的主要功能是从控制台读取域名和端口。域名和端口通过":"隔开,":"和域名以及端口之间不能有空格。当从控制台读取一个"q"时,这个函数返回false,表示程序可以退出了,否则返回true,表示输入的域名和端口是正确的。这个方法的实现代码如下:

001privatebooleanreadHostAndPort(BufferedReader consoleReader)002throwsException003{004System.out.print("host:port>");005String[] ss=null;006String s=consoleReader.readLine();007if(s.equals("q"))008returnfalse;009else010{011ss=s.split("[:]");012if(!ss[0].equals(""))013host=ss[0];014if(ss.length>1)015port=Integer.parseInt(ss[1]);016System.out.println(host+":"+String.valueOf(port));017returntrue;018}019}

第001行:这个方法有一个BufferedReader类型的参数,这个参数的值就是在HttpSimulator.java中的第016和017行根据控制台输入流建立的BufferedReader对象。

第 004 行:这输出HTTP模拟器的控制符,就象Windows的控制台的"C:">"一样。

第 006 行:从控制台读取一行字符串。

第 011 行:通过字符串的split方法和响应的正则表示式("[:]")将域名和端口分开。域名的默认值是localhost,端口的默认值是80。

三、readHttpRequest(...)方法的实现

这个方法的主要功能是从控制台读取HTTP请求消息,如果输入一个空行,表示请求消息头已经输完;如果使用的是POST方法,还要输入POST请求的实体内容。这个方法的实现代码如下:

001privatevoidreadHttpRequest(BufferedReader consoleReader)002throwsException003{004System.out.println("请输入HTTP请求:");005String s=consoleReader.readLine();006request=s+"\r\n";007booleanisPost=s.substring(0,4).equals("POST");008booleanisHead=s.substring(0,4).equals("HEAD");009while(!(s=consoleReader.readLine()).equals(""))010request=request+s+"\r\n";011request=request+"\r\n";012if(isPost)013{014System.out.println("请输入POST方法的内容:");015s=consoleReader.readLine();016request=request+s;017}018}

第 005 行:读入HTTP请求消息的第一行。

第 007、008行:确定所输入的请求方法是不是POST和HEAD。

第 009、010行:读入HTTP请求消息的其余行。

第012?017行:如果HTTP请求使用的是POST方法,要求用户继续输入HTTP请求的实体内容。

四、sendHttpRequest()方法的实现

这个方法的功能是将request变量中的HTTP请求消息发送到服务器。下面是这个方法的实现代码:

001privatevoidsendHttpRequest()throwsException002{003socket=newSocket();004socket.setSoTimeout(10*1000);005System.out.println("正在连接服务器9b8a8a44dd1c74ae49c20a7cd451974e.png");006socket.connect(newInetSocketAddress(host, port),10*1000);007System.out.println("服务器连接成功!");008OutputStream out=socket.getOutputStream();009OutputStreamWriter writer=newOutputStreamWriter(out);010writer.write(request);011writer.flush();012}

第004行:设置读取数据超时为10秒。

第006行:连接服务器,并设置连接超时为10秒。五、readHttpResponse(...)方法的实现

这个方法的主要功能是从服务器读取返回的响应消息。首先读取了响应消息头,然后要求用户输入Y或N以确定是否显示响应消息的实体内容。这个程序之所以这样做,主要有两个原因:

(1)为了研究HTTP协议。

(2)由于本程序是以字符串形式显示响应消息的,因此,如果用户请求了一个二进制Web资源,如一个rar文件,那么实体内容将会显示乱码。所以在显示完响应消息头后由用户决定是否显示实体内容。

这个方法的实现代码如下:

001privatevoidreadHttpResponse(BufferedReader consoleReader)002{003String s="";004try005{006InputStream in=socket.getInputStream();007InputStreamReader inReader=newInputStreamReader(in);008BufferedReader socketReader=newBufferedReader(inReader);009System.out.println("---------HTTP头---------");010booleanb=true;//true: 未读取消息头 false: 已经读取消息头011while((s=socketReader.readLine())!=null)012{013if(s.equals("")&&b==true&&!isHead)014{015System.out.println("------------------------");016b=false;017System.out.print("是否显示HTTP的内容(Y/N):");018String choice=consoleReader.readLine();019if(choice.equals("Y")||choice.equals("y"))020{021System.out.println("---------HTTP内容---------");022continue;023}024else025break;026}027else028System.out.println(s);029}030}031catch(Exception e)032{033System.out.println("err:"+e.getMessage());034}035finally036{037try038{039socket.close();040}041catch(Exception e)042{043}044}045System.out.println("------------------------");046}

在上面的代码中013行 是最值得注意的。其中s.equals("")表示读入一个空行(表明消息头已经结束);由于在实体内容中也可以存在空行,因此,b == true来标记消息头是否已经被读过,当读完消息头后,将b设为false,如果以后再遇到空行,就不会当成消息头来处理了。当HTTP请求使用HEAD 方法时,服务器只返回响应消息头;因此,使用!isHead来保证使用HEAD发送请求时不显示响应消息的内容实体。

现在我们已经实现了这个HTTP模拟器,下面让我们来运行并测试它。

运行

运行如下的命令

java http.HttpSimulator

运行以上的命令后,将显示如图1所示的界面。

zoom.gif56ba2630f0f5af0644f09a7033d20d41.png

图1

测试

在HTTP模拟器中输入如下的域名:

www.csdn.net

在HTTP模拟器中输入如下的HTTP请求消息:

GET/HTTP/1.1Host: www.csdn.net

运行的结果如图2所示。

zoom_h.gifaeb1948065ddf478e806d53b7f918a23.png

图2

读者可以从本文的开始部分下载Http模拟器的源代码和.class文件。

CSDN

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值