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();
  }
 }

}

原文地址:https://www.cnblogs.com/kernel-style/p/3311770.html