现在的位置: 首页 > 综合 > 正文

java实现简单web服务器(分析+源代码)

2018年03月20日 ⁄ 综合 ⁄ 共 2833字 ⁄ 字号 评论关闭

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

                                                                   HTTP 请求报文

                                                         

                            HTTP 响应报文


   web服务器获取一个用户的连接时,会初始化一个线程和用户通信,代码如下:

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;


//每有一个连接建立时,服务器分出一个通信的线程
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());
		}		
	}
	


}

服务器主要负责初始化套接字和线程,代码如下:

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”,就可以看到位于服务器端的html文件了。注意由于服务器是死循环,重启服务器会发现指定的端口已被绑定,只需要进入任务管理器,关闭"Java(TM) Platfrom SE binary"进程即可。最后结果如下所示:

这个服务器程序很简陋,还有很大的改进余地。大家可以自己尝试改进。这里可以尝试一下访问其他的文件,发现时成功的,说明这服务器很不安全呀。



抱歉!评论已关闭.