zoukankan      html  css  js  c++  java
  • java实现简单webserver(分析+源码)

        在日常的开发中,我们用过非常多开源的webserver,比如tomcat、apache等等。如今我们自己实现一个简单的webserver,主要的功能就是用户点击要訪问的资源,server将资源发送到client的浏览器。为了简化操作。这里不考虑资源不存在等异常情况。web服务基于的是HTTP协议。用户在浏览器的地址栏输入要訪问的地址,server怎样得到该地址是个关键。先看下一般的HTTP请求和响应报文的一般格式:

                                                                       HTTP 请求报文

                                                             

                                HTTP 响应报文


       webserver获取一个用户的连接时,会初始化一个线程和用户通信,代码例如以下:

    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.Socket;
    
    
    //每有一个连接建立时,server分出一个通信的线程
    public class CommunicateThread extends Thread{
    	//与客户端通信的套接字
    	Socket client;
    	
    	public CommunicateThread(Socket s) {
    		client = s;
    	}
    	
    	//获取浏览器请求资源的路径
    	public String getResourcePath(String s){
    		// 一般的HTTP请求报文的第一行是“GET /index.html HTTP/1.1”
    		// 我们要获取的就是中间的"/indext.apsx"
    		
    		//获取资源的位置
    		String s1 = s.substring(s.indexOf(' ')+1);
    		s1 = s1.substring(1,s1.indexOf(' '));
    		
    		//默认资源为index.html
    		if(s1.equals(""))
    			s1 = "index.html";
    		
    		return s1;
    	}
    
    	public void sendFile(PrintStream out,File file){
    		try{
    			DataInputStream in  = new DataInputStream(new FileInputStream(file));
    			int len = (int)file.length();
    			byte buf[] = new byte[len];
    			in.readFully(buf);//读取文内容到buf数组中
    			out.write(buf,0,len);
    			out.flush();
    			in.close();
    		}
    		catch(Exception e){
    			System.out.println(e.getMessage());
    			System.exit(1);
    			}
    	}
    	
    	public void run(){
    		try{
    			//获取用户的IP地址和端口号
    			String clientIP = client.getInetAddress().toString();
    			int clientPort = client.getPort();
    			//创建输出流对象
    			PrintStream out = new PrintStream(client.getOutputStream());
    			//创建输入流对象
    			DataInputStream in = new DataInputStream(client.getInputStream());
    			//读取浏览器提交的请求
    			String msg = in.readLine();
    			
    			
    			//获取文件路径
    			String fileName = getResourcePath(msg);
    			System.out.println("The user asked for resource: "+fileName);
    			File file = new File(fileName);
    			
    			if(file.exists()){
    				//依据响应报文格式设置
    				System.out.println(fileName+" start send");
    				
    				out.println("HTTP/1.0 200 OK"); 
    				out.println("MIME_version:1.0");
    				out.println("Content_Type:text/html");
    				int len = (int) file.length();
    				out.println("Content_Length:"+len);
    				out.println("");//报文头和信息之间要空一行
    				
    				//发送文件
    				sendFile(out,file);
    				
    				out.flush();
    			}	
    			client.close();		
    		}
    		catch(Exception e){
    			System.out.println(e.getMessage());
    		}		
    	}
    	
    
    
    }
    

    server主要负责初始化套接字和线程。代码例如以下:

    import java.net.ServerSocket;
    import java.net.Socket;
    
    
    public class WebServer {
    
    
    	public static void main(String[] args) {
    		int Port = 12345;//端口号,因为这里是測试,所以不要使用经常使用端口
    		//创建两个套接字
    		ServerSocket server = null;
    		Socket client = null;
    		try{
    			server = new ServerSocket(Port);
    			//服务器開始监听
    			System.out.println("The WebServer is listening on port "+server.getLocalPort());
    			while(true){
    				client = server.accept();
    				//多线程执行
    				new CommunicateThread(client).start();
    			}
    		}catch(Exception e){
    			System.out.println(e.getMessage());
    		}
    	}
    
    }
    


    执行測试:

    编写一个index.html文件

    <html>
    <head></head>
    <body>
    <h1>This is the index of my WebServer</h1><hr></body>
    </html>
    放到项目文件的根文件夹,然后在浏览器地址栏输入:“localhost:12345/index.html”,就能够看到位于server端的html文件了。注意因为server是死循环,重新启动server会发现指定的port已被绑定,仅仅须要进入任务管理器,关闭"Java(TM) Platfrom SE binary"进程就可以。最后结果例如以下所看到的:


    这个server程序非常简陋,还有非常大的改进余地。

    大家能够自己尝试改进。这里能够尝试一下訪问其它的文件,发现时成功的。说明这server非常不安全呀。




  • 相关阅读:
    20145120 《Java程序设计》第5周学习总结
    20145120 《Java程序设计》第4周学习总结
    20145120 《Java程序设计》第3周学习总结
    20145120 《Java程序设计》第2周学习总结
    20145120 《Java程序设计》第1周学习总结
    you build it,you run it
    我们为什么要研究docker
    他们为什么选择前端工程化,而我又是基于什么考虑的
    Jboss性能调优
    理解Tomcat架构、启动流程及其性能优化
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7345766.html
Copyright © 2011-2022 走看看