您现在的位置是:首页 >

Java网络编程从入门到精通(22):实现HTTP模拟器

火烧 2023-01-16 00:15:04 1057
Java网络编程从入门到精通(22):实现HTTP模拟器   专题推荐 网络编程 基础到进阶教程  在讨论HTTP协议的具体请求和响应头字段之前 让我们先来利用以前所学的知识来实现一个HTTP模拟器

Java网络编程从入门到精通(22):实现HTTP模拟器  

  专题推荐 网络编程 基础到进阶教程

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

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

     接收服务器的响应消息

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

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

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

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

   可以循环做上述的操作

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

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

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

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

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

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

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

  一 建立一个大循环

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

       package ;          import  *;     import java io *;          public class HttpSimulator     {         private Socket socket;         private int port =  ;         private String host =  localhost ;         private String request =  ; // HTTP请求消息         private boolean isPost  isHead;                   public void run() throws Exception         {             BufferedReader reader = new BufferedReader(new InputStreamReader(                     System in));             while (true)  // 开始大循环             {                 try                 {                     if (!readHostAndPort(reader))                         break;                     readHttpRequest(reader);                     sendHttpRequest();                     readHttpResponse(reader);                 }                 catch (Exception e)                 {                     System out println( err:  + e getMessage());                 }             }         }         public static void main(String[] args) throws Exception         {             new HttpSimulator() run();         }     }

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

  二 readHostAndPort(……)方法的实现

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

        private boolean readHostAndPort(BufferedReader consoleReader)             throws Exception     {         System out print( host:port> );         String[] ss = null;         String s = consoleReader readLine();         if (s equals( q ))             return false;         else         {             ss = s split( [:] );             if (!ss[ ] equals( ))                 host = ss[ ];             if (ss length >  )                 port = Integer parseInt(ss[ ]);             System out println(host +  :  + String valueOf(port));             return true;         }     }

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

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

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

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

  三 readHttpRequest(……)方法的实现

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

        private void readHttpRequest(BufferedReader consoleReader)              throws Exception     {         System out println( 请输入HTTP请求: );         String s = consoleReader readLine();         request = s +  rn ;         boolean isPost = s substring(   ) equals( POST );         boolean isHead = s substring(   ) equals( HEAD );         while (!(s = consoleReader readLine()) equals( ))             request = request + s +  rn ;         request = request +  rn ;         if (isPost)         {             System out println( 请输入POST方法的内容: );             s = consoleReader readLine();             request = request + s;         }     }

  第 行 读入HTTP请求消息的第一行

  第 行 确定所输入的请求方法是不是POST和HEAD

  第 行 读入HTTP请求消息的其余行

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

  四 sendHttpRequest()方法的实现

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

            private void sendHttpRequest() throws Exception         {             socket = new Socket();             socket setSoTimeout(  *  );             System out println( 正在连接服务器 );             nnect(new InetSocketAddress(host  port)    *  );             System out println( 服务器连接成功! );             OutputStream out = socket getOutputStream();             OutputStreamWriter writer = new OutputStreamWriter(out);             writer write(request);             writer flush();         }

  第 行 设置读取数据超时为 秒

  第 行 连接服务器 并设置连接超时为 秒

  五 readHttpResponse(……)方法的实现

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

  ( ) 为了研究HTTP协议

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

  这个方法的实现代码如下

        private void readHttpResponse(BufferedReader consoleReader)     {         String s =  ;         try         {             InputStream in = socket getInputStream();             InputStreamReader inReader = new InputStreamReader(in);             BufferedReader socketReader = new BufferedReader(inReader);             System out println( HTTP头 );             boolean b = true; // true: 未读取消息头 false: 已经读取消息头             while ((s = socketReader readLine()) != null)             {                 if (s equals( ) && b == true && !isHead)                 {                     System out println( );                     b = false;                     System out print( 是否显示HTTP的内容(Y/N): );                     String choice = consoleReader readLine();                     if (choice equals( Y ) || choice equals( y ))                     {                         System out println( HTTP内容 );                         continue;                     }                     else                         break;                 }                 else                     System out println(s);             }         }         catch (Exception e)         {             System out println( err:  + e getMessage());         }         finally         {             try             {                 socket close();             }             catch (Exception e)             {             }         }         System out println( );     }

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

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

  运行

  运行如下的命令

   java  HttpSimulator

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

  测试

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

  

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

Java网络编程从入门到精通(22):实现HTTP模拟器

   GET / HTTP/ Host

  运行的结果如图 所示

  

lishixinzhi/Article/program/Java/hx/201311/26047  
永远跟党走
  • 如果你觉得本站很棒,可以通过扫码支付打赏哦!

    • 微信收款码
    • 支付宝收款码