zoukankan      html  css  js  c++  java
  • http协议

     Web服务器与客户端的通信使用HTTP协议(超文本传输协议),所以也叫做HTTP服务器。用Java构造Web服务器主要用二个类,java.net.Socket和java.net.ServerSocket,来实现HTTP通信。因此,本文首先要讨论的是HTTP协议和这两个类,在此基础上实现一个简单但完整的Web服务器。
      一、超文本传输协议
      Web服务器和浏览器通过HTTP协议在Internet上发送和接收消息。HTTP协议是一种请求-应答式的协议——客户端发送一个请求,服务器返回该请求的应答。HTTP协议使用可靠的TCP连接,默认端口是80。HTTP的第一个版本是HTTP/0.9,后来发展到了HTTP/1.0,现在最新的版本是HTTP/1.1。HTTP/1.1由
     RFC 2616 定义(pdf格式)。
      本文只简要介绍HTTP 1.1的相关知识,但应该足以让你理解Web服务器和浏览器发送的消息。如果你要了解更多的细节,请参考RFC 2616。
      在HTTP中,客户端/服务器之间的会话总是由客户端通过建立连接和发送HTTP请求的方式初始化,服务器不会主动联系客户端或要求与客户端建立连接。浏览器和服务器都可以随时中断连接,例如,在浏览网页时你可以随时点击“停止”按钮中断当前的文件下载过程,关闭与Web服务器的HTTP连接。
      1.1 HTTP请求
      HTTP请求由三个部分构成,分别是:方法-URI-协议/版本,请求头,请求正文。下面是一个HTTP请求的例子:
    GET /servlet/default.jsp HTTP/1.1
    Accept: text/plain; text/html 
    Accept-Language: en-gb 
    Connection: Keep-Alive 
    Host: localhost 
    Referer: http://localhost/ch8/SendDetails.htm 
    User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98) 
    Content-Length: 33 
    Content-Type: application/x-www-form-urlencoded 
    Accept-Encoding: gzip, deflate 
    userName=JavaJava&userID=javaID

     请求的第一行是“方法-URI-协议/版本”,其中GET就是请求方法,/servlet/default.jsp表示URI,HTTP/1.1是协议和协议的版本。根据HTTP标准,HTTP请求可以使用多种请求方法。例如,HTTP 1.1支持七种请求方法:GET,POST,HEAD,OPTIONS,PUT,DELETE,和TRACE。在Internet应用中,最常用的请求方法是GET和POST。
      URI完整地指定了要访问的网络资源,通常认为它相对于服务器的根目录而言,因此总是以“/”开头。URL实际上是
    URI 一种类型。最后,协议版本声明了通信过程中使用的HTTP协议的版本。
      请求头包含许多有关客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度,等等,它们之间用一个回车换行符号(CRLF)分隔。
      请求头和请求正文之间是一个空行(只有CRLF符号的行),这个行非常重要,它表示请求头已经结束,接下来的是请求的正文。一些介绍Internet编程的书籍把这个CRLF视为HTTP请求的第四个组成部分。
      在前面的HTTP请求中,请求的正文只有一行内容。当然,在实际应用中,HTTP请求正文可以包含更多的内容。
      1.2 HTTP应答
      和HTTP请求相似,HTTP应答也由三个部分构成,分别是:协议-状态代码-描述,应答头,应答正文。下面是一个HTTP应答的例子:
    HTTP/1.1 200 OK
    Date: Tue, 06 Mar 2012 12:32:58 GMT
    Server: Apache/2.2.22 (Win32)
    Last-Modified: Tue, 06 Mar 2012 11:46:06 GMT
    ETag: “b000000008d9e-57-4ba9196947acd”
    Accept-Ranges: bytes
    Content-Length: 87
    Content-Type: text/html

    经过测试,可以使用滴
    //实例一:
    package com.abin.lii.han.socket;

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.URLEncoder;

    public class SocketGetServletTest {
     public static void main(String[] args) {
       BufferedWriter httpGetWriter = null; 
             BufferedReader httpResponse = null; 
             try { 
                 String hostname = "localhost";// 主机,可以是域名,也可以是ip地址 
                 int port = 1443;// 端口 
                 InetAddress addr = InetAddress.getByName(hostname); 
                 // 建立连接 
                 Socket socket = new Socket(addr, port); 
                 // 创建数据提交数据流 
                 httpGetWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "GBK")); 
                 // 相对主机的请求地址 
                 StringBuffer httpSubmitPath = new StringBuffer("/abin/ImediaRegister?"); 
    //             StringBuffer httpSubmitPath = new StringBuffer("http://localhost:7200/abin/ImediaRegister?"); 
                 httpSubmitPath.append(URLEncoder.encode("app", "GBK")); 
                 httpSubmitPath.append("="); 
                 httpSubmitPath.append(URLEncoder.encode("longcodeimedia", "GBK")); 
                 httpSubmitPath.append("&"); 
                 httpSubmitPath.append(URLEncoder.encode("udid", "GBK")); 
                 httpSubmitPath.append("="); 
                 httpSubmitPath.append(URLEncoder.encode("123456789", "GBK")); 
                 httpSubmitPath.append("&"); 
                 httpSubmitPath.append(URLEncoder.encode("source", "GBK")); 
                 httpSubmitPath.append("="); 
                 httpSubmitPath.append(URLEncoder.encode("limei", "GBK")); 
                 httpSubmitPath.append("&"); 
                 httpSubmitPath.append(URLEncoder.encode("returnFormat", "GBK")); 
                 httpSubmitPath.append("="); 
                 httpSubmitPath.append(URLEncoder.encode("2", "GBK")); 
                 httpGetWriter.write("GET " + httpSubmitPath.toString() + " HTTP/1.1 "); 
                 httpGetWriter.write("Host: localhost:7200 "); 
                 httpGetWriter.write("UserAgent: IE8.0 ");
                 httpGetWriter.write("Connection: Keep-Alive ");
                 httpGetWriter.write(" "); 
                 httpGetWriter.flush(); 
                 // 创建web服务器响应的数据流 
                 httpResponse = new BufferedReader(new InputStreamReader(socket.getInputStream(), "GBK")); 
                 // 读取每一行的数据.注意大部分端口操作都需要交互数据。 
                 String lineStr = ""; 
                 while ((lineStr = httpResponse.readLine()) != null) { 
                     System.out.println(lineStr); 
                 } 
             } catch (Exception e) { 
                 e.printStackTrace(); 
             } finally { 
                 try { 
                     if (httpGetWriter != null) { 
                         httpGetWriter.close(); 
                     } 
                     if (httpResponse != null) { 
                         httpResponse.close(); 
                     } 
                 } catch (IOException e) { 
                     e.printStackTrace(); 
                 } 
             } 
         }

            
    }



    //实例二

    package com.abin.lii.han.socket;

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.net.InetAddress;
    import java.net.Socket;

    public class SocketGetServletTest1 {

     public static void main(String[] args) {
      try {
       Socket socket = new Socket(InetAddress.getLocalHost(), 7200);
       BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
       StringBuffer buffer = new StringBuffer();
       buffer.append("GET http://localhost:7200/abin/ImediaRegister?app=2 HTTP/1.1 ");
       buffer.append("Host: localhost:7200 ");
       buffer.append("UserAgent: IE8.0 ");
       buffer.append("Connection: Keep-Alive ");
       // 注,这是关键的关键,忘了这里让我搞了半个小时。这里一定要一个回车换行,表示消息头完,不然服务器会等待
       buffer.append(" ");
       writer.write(buffer.toString());
       writer.flush();

       // --输出服务器传回的消息的头信息
       BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
       String line = null;
       StringBuilder builder=new StringBuilder();
       while((line=reader.readLine())!=null){
        builder.append(line);
       }
       String result=builder.toString();
       System.out.println("result="+result);
      } catch (Exception e) {
       e.printStackTrace();
      }
     }

    }

  • 相关阅读:
    2020.4.10个人总结
    CG-CTF simple machine
    CG-CTF Our 16bit wars
    CG-CTF Our 16bit Games
    CG-CTF single
    CG-CTF WxyVM2
    Go Channel 详解
    Go语言TCP Socket编程
    golang mysql demo
    YouCompleteMe unavailable: requires Vim compiled with Python 2.x support
  • 原文地址:https://www.cnblogs.com/kernel-style/p/3311770.html
Copyright © 2011-2022 走看看