Java实践:一个简易的http server和client的java源码学习和总结。

时间:2022-01-26 14:15:01

一、基本思路:

1、服务器端通过socket(), 监听在TCP 8080端口,等待客户端来连接。

2、服务器端解析客户端的HTTP请求中的URI值,把本地的目录下指定文件通过java的读取文件的方式getResourceAsStream()发送给客户端。

3、客户端把应用程序的第一个参数作为目标文件,传到HTTP请求中。

 

二、总结:

1、服务器端终究是通过解析HTTP请求中的内容,取到目标文件,并且服务器端的字节码文件,必须和root目录放一起。

2、java有现成的类的方法,获得socket中的内容,服务器端的成功返回,也是服务器自行构造的。

 

三、源码

1、服务器端代码:

  1 package server;
  2 import java.io.*;
  3 import java.net.*;
  4 
  5 public class HTTPServer{
  6   public static void main(String args[]) {
  7     int port;
  8     ServerSocket serverSocket;
  9       
 10     try { 
 11        port = Integer.parseInt(args[0]);
 12      }catch (Exception e) {
 13        System.out.println("port = 8080 (默认)");
 14        port = 8080; //默认端口为8080
 15      }
 16 
 17      try{
 18        serverSocket = new ServerSocket(port); 
 19        System.out.println("服务器正在监听端口:" + serverSocket.getLocalPort());
 20         
 21        while(true) { //服务器在一个无限循环中不断接收来自客户的TCP连接请求
 22          try{
 23            //等待客户的TCP连接请求
 24            final Socket socket = serverSocket.accept(); 
 25            System.out.println("建立了与客户的一个新的TCP连接,该客户的地址为:"+
 26                 socket.getInetAddress()+":" + socket.getPort());
 27           
 28            service(socket);  //响应客户请求
 29         }catch(Exception e){e.printStackTrace();} 
 30       } //#while
 31     }catch (Exception e) {e.printStackTrace();}
 32   }
 33 
 34   /** 响应客户的HTTP请求 */
 35   public static void service(Socket socket)throws Exception{
 36     
 37     /*读取HTTP请求信息*/
 38     InputStream socketIn=socket.getInputStream(); //获得输入流
 39     Thread.sleep(500);  //睡眠500毫秒,等待HTTP请求  
 40     int size=socketIn.available();
 41     byte[] requestBuffer=new byte[size];
 42     socketIn.read(requestBuffer);
 43     String request=new String(requestBuffer);
 44     System.out.println(request); //打印HTTP请求数据
 45      
 46     /*解析HTTP请求*/
 47     //获得HTTP请求的第一行
 48     String firstLineOfRequest=request.substring(0,request.indexOf("\r\n"));
 49     //解析HTTP请求的第一行 
 50     String[] parts=firstLineOfRequest.split(" ");
 51     String getMethod = "GET";
 52     if(true != parts[0].equals("GET"))
 53     {
 54         System.out.println("client Bad request:" + parts[0] + " method length=" + parts[0].length() ); //打印错误的请求
 55         System.out.println("correct request is:" + getMethod ); 
 56     }
 57     
 58     String uri=parts[1]; //获得HTTP请求中的uri
 59     
 60     /*决定HTTP响应正文的类型*/
 61     String contentType;
 62     if(uri.indexOf("html")!=-1 || uri.indexOf("htm")!=-1)
 63       contentType="text/html";
 64     else if(uri.indexOf("jpg")!=-1 || uri.indexOf("jpeg")!=-1)
 65       contentType="image/jpeg";
 66     else if(uri.indexOf("gif")!=-1) 
 67       contentType="image/gif";
 68     else
 69       contentType="application/octet-stream"; 
 70     
 71     
 72     /*创建HTTP响应结果 */
 73     //HTTP响应的第一行
 74     String responseFirstLine="HTTP/1.1 200 OK\r\n";
 75     //HTTP响应头
 76     String responseHeader="Content-Type:"+contentType+"\r\n\r\n";
 77     //获得读取响应正文数据的输入流
 78     InputStream in=HTTPServer.class.getResourceAsStream("root/"+uri);
 79     
 80     /*发送HTTP响应结果 */
 81     OutputStream socketOut=socket.getOutputStream(); //获得输出流
 82     //发送HTTP响应的第一行
 83     socketOut.write(responseFirstLine.getBytes());
 84     //发送HTTP响应的头
 85     socketOut.write(responseHeader.getBytes());
 86     //发送HTTP响应的正文
 87     int len=0;
 88     byte[] buffer=new byte[128];
 89     while((len=in.read(buffer))!=-1)
 90     socketOut.write(buffer,0,len);  
 91     
 92     Thread.sleep(1000);  //睡眠1秒,等待客户接收HTTP响应结果        
 93     socket.close(); //关闭TCP连接  
 94     
 95   }
 96 }
 97 
 98 
 99 
100 
101 /****************************************************
102  * 作者:孙卫琴                                     *
103  * 来源:<<Tomcat与Java Web开发技术详解>>           *
104  * 技术支持网址:www.javathinker.org                *
105  ***************************************************/

 

客户端代码:

 1 package client;
 2 import java.net.*;
 3 import java.io.*;
 4 import java.util.*;
 5 
 6 public class HTTPClient {
 7   public static void main(String args[]){
 8     //确定HTTP请求的uri
 9     String uri="index.htm";
10     if(args.length !=0)uri=args[0]; 
11     
12     doGet("localhost",8080,uri); //按照GET请求方式访问HTTPServer 
13   }
14   
15   /** 按照GET请求方式访问HTTPServer */
16   public static void doGet(String host,int port,String uri){
17     Socket socket=null;
18     
19     try{
20       socket=new Socket(host,port); //与HTTPServer建立FTP连接
21     }catch(Exception e){e.printStackTrace();}
22   
23     try{
24       /*创建HTTP请求 */
25       StringBuffer sb=new StringBuffer("GET1 "+uri+" HTTP/1.1\r\n");
26       sb.append("Accept: */*\r\n");
27       sb.append("Accept-Language: zh-cn\r\n");
28       sb.append("Accept-Encoding: gzip, deflate\r\n");
29       sb.append("User-Agent: HTTPClient\r\n");
30       sb.append("Host: localhost:8080\r\n");
31       sb.append("Connection: Keep-Alive\r\n\r\n");
32     
33       /*发送HTTP请求*/
34       OutputStream socketOut=socket.getOutputStream(); //获得输出流  
35       socketOut.write(sb.toString().getBytes());
36     
37       Thread.sleep(2000); //睡眠2秒,等待响应结果
38     
39       /*接收响应结果*/
40       InputStream socketIn=socket.getInputStream(); //获得输入流
41       int size=socketIn.available();
42       byte[] buffer=new byte[size];
43       socketIn.read(buffer);
44       System.out.println(new String(buffer)); //打印响应结果
45       
46     }catch(Exception e){ 
47       e.printStackTrace();
48     }finally{
49       try{
50         socket.close();  
51       }catch(Exception e){e.printStackTrace();}
52     }
53   } //#doGet()
54 }
55 
56 
57 
58 
59 /****************************************************
60  * 作者:孙卫琴                                     *
61  * 来源:<<Tomcat与Java Web开发技术详解>>           *
62  * 技术支持网址:www.javathinker.org                *
63  ***************************************************/

 

四、运行方法:

1、先运行服务器端,以便等待客户端的连接:

     Java实践:一个简易的http server和client的java源码学习和总结。

 2、再启动客户端,发送http 请求:

       Java实践:一个简易的http server和client的java源码学习和总结。

3、观察服务器端的输出:

    Java实践:一个简易的http server和client的java源码学习和总结。

    特别说明,在本程序中,已经判断出客户端写错了GET请求,写成了GET1,但是,这里判断不严格,只是捕获出来了,但是不影响程序继续运行。