一个使用ThreadPoolExecutor线程池实现的简单的HTTP服务器_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 一个使用ThreadPoolExecutor线程池实现的简单的HTTP服务器

一个使用ThreadPoolExecutor线程池实现的简单的HTTP服务器

 2013/9/30 16:11:16  xglv2013  程序员俱乐部  我要评论(0)
  • 摘要:这里使用javasocket和concurrent包里的ThreadPoolExecutor实现了一个小型的HTTP服务器,管理入站请求,代码如下:packagejHttpNew;importjava.net.*;importjava.io.*;importjava.util.concurrent.ArrayBlockingQueue;importjava.util.concurrent.ThreadPoolExecutor;importjava.util.concurrent
  • 标签:实现 使用 thread 一个 服务器 服务 线程 HTTP
这里使用java socket和concurrent包里的ThreadPoolExecutor实现了一个小型的HTTP服务器,管理入站请求,代码如下:

class="java" name="code">package jHttpNew;

import java.net.*;
import java.io.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class JHTTP extends Thread 
{
	//文件所在目录
	private File documentRootDirectory;
	//默认的文件名
	private String indexFileName = "index.html";
	private ServerSocket server;
    
	public JHTTP(File documentRootDirectory, int port, String indexFileName) throws IOException
	{
		if (!documentRootDirectory.isDirectory())
		{
			throw new IOException(documentRootDirectory + " does not exist as a directory"); 
		}
		this.documentRootDirectory = documentRootDirectory;
		this.indexFileName = indexFileName;
		this.server = new ServerSocket(port);
	}

	public JHTTP(File documentRootDirectory, int port) throws IOException
	{
		this(documentRootDirectory, port, "index.html");
	}

	public JHTTP(File documentRootDirectory) throws IOException 
	{
		this(documentRootDirectory, 80, "index.html");
	}

	public void run()
	{
		//建立一个Http Request线程池
		ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 4, 3,TimeUnit.SECONDS, 
				new ArrayBlockingQueue<Runnable>(3),new ThreadPoolExecutor.AbortPolicy());
	
		System.out.println("Accepting connections on port " + server.getLocalPort());
		System.out.println("Document Root: " + documentRootDirectory);
		while (true)
		{
			try
			{
				//使用服务器端socket,接受http请求
				Socket request = server.accept();
				//用线程池处理http请求
				threadPool.execute(new ThreadPoolTask(documentRootDirectory, indexFileName, request));
			}
			catch (IOException ex) 
			{ 
			}   
		}  
	}
  
	public static void main(String[] args)
	{
	    // get the Document root
	    File docroot;
	    try 
	    {
	    	docroot = new File("C:/jhttp_test");
	    }
	    catch (ArrayIndexOutOfBoundsException ex) 
	    {
	    	System.out.println("Usage: java JHTTP docroot port indexfile");
	    	return;
	    }
	    
	    // set the port to listen on
	    int port;
	    try 
	    {
	    	port = Integer.parseInt(args[1]);
	    	if (port < 0 || port > 65535) port = 80;
	    }  
	    catch (Exception ex)
	    {
	    	port = 80;
	    }  
	    
	    try 
	    {            
	    	JHTTP webserver = new JHTTP(docroot, port);
            webserver.start();
	    }
	    catch(IOException ex) 
	    {
	    	System.out.println("Server could not start because of an " + ex.getClass());
	    	System.out.println(ex);
	    }
  
	}

}


package jHttpNew;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Serializable;
import java.io.Writer;
import java.net.Socket;
import java.util.Date;
import java.util.StringTokenizer;

public class ThreadPoolTask implements Runnable, Serializable
{
	
	private static final long serialVersionUID = 0;
	private File documentRootDirectory;
	private String indexFileName = "index.html";
	private Object threadPoolTaskData;
	ThreadPoolTask(File documentRootDirectory, 
			   String indexFileName,
			   Object tasks)
	{
		if (documentRootDirectory.isFile())
		{
		    throw new IllegalArgumentException("documentRootDirectory must be a directory, not a file"); 
		}
		this.documentRootDirectory = documentRootDirectory;
		try 
		{
		    this.documentRootDirectory = documentRootDirectory.getCanonicalFile();
		}
		catch (IOException ex)
		{
		}
		if (indexFileName != null) 
			this.indexFileName = indexFileName;
		this.threadPoolTaskData = tasks;
	}
	public void run() 
	{    
	    // for security checks
	    String root = documentRootDirectory.getPath();
	        
	    // 建立socket connection对象
	    Socket connection;
	    connection = (Socket) threadPoolTaskData; 

	    try 
	    {            
	        String filename;
	        String contentType;   
	        OutputStream raw = new BufferedOutputStream(
	                            connection.getOutputStream()
	                           );         
	        Writer out = new OutputStreamWriter(raw);
	        Reader in = new InputStreamReader(
	                     new BufferedInputStream(
	                      connection.getInputStream()
	                     ),"ASCII"
	                    );
	        StringBuffer requestLine = new StringBuffer();
	        
	        //读取输入流,这里只读第一行
	        int c;
	        while (true)
	        {
	            c = in.read();
	            if (c == '\r' || c == '\n') break;
	            requestLine.append((char) c);
	        }
	        
	        String get = requestLine.toString();
	        
	        // log the request 
	        System.out.println(get);
	        
	        StringTokenizer st = new StringTokenizer(get);
	        String method = st.nextToken();
	        String version = "";
	        if (method.equals("GET"))
	        {
	            filename = st.nextToken();
	            if (filename.endsWith("/")) filename += indexFileName;
	            contentType = guessContentTypeFromName(filename);
	            if (st.hasMoreTokens())
	            {
	            	version = st.nextToken();
	            }

	            File theFile = new File(documentRootDirectory, 
	            filename.substring(1,filename.length()));
	            if (theFile.canRead() 
	              // Don't let clients outside the document root
	            		&& theFile.getCanonicalPath().startsWith(root)) 
	            {
	            	DataInputStream fis = new DataInputStream(
	                                   new BufferedInputStream(
	                                    new FileInputStream(theFile)
	                                   )
	                                  );
	            byte[] theData = new byte[(int) theFile.length()];
	            fis.readFully(theData);
	            fis.close();
	            if (version.startsWith("HTTP "))
	            {   // send a MIME header
	                out.write("HTTP/1.0 200 OK\r\n");
	                Date now = new Date();
	                out.write("Date: " + now + "\r\n");
	                out.write("Server: JHTTP/1.0\r\n");
	                out.write("Content-length: " + theData.length + "\r\n");
	                out.write("Content-type: " + contentType + "\r\n\r\n");
	                out.flush();
	            }  // end if
	        
	            // send the file; it may be an image or other binary data 
	            // so use the underlying output stream 
	            // instead of the writer
	            raw.write(theData);
	            raw.flush();
	            }  // end if
	            
	            //如果文件不存在,返回404
	            else
	            {  // can't find the file
	                if (version.startsWith("HTTP "))
	                {  // send a MIME header
	                    out.write("HTTP/1.0 404 File Not Found\r\n");
	                    Date now = new Date();
	                    out.write("Date: " + now + "\r\n");
	                    out.write("Server: JHTTP/1.0\r\n");
	                    out.write("Content-type: text/html\r\n\r\n");
	                } 
	                out.write("<HTML>\r\n");
	                out.write("<HEAD><TITLE>File Not Found</TITLE>\r\n");
	                out.write("</HEAD>\r\n");
	                out.write("<BODY>");
	                out.write("<H1>HTTP Error 404: File Not Found</H1>\r\n");
	                out.write("</BODY></HTML>\r\n");
	                out.flush();
	            }
	        }
	        
	        //这里只是先实现了GET方法,如果用户没有输入GET,那么返回501的返回码,表示方法未实现
	        else 
	        {   // method does not equal "GET"
	            if (version.startsWith("HTTP "))
	            {  // send a MIME header
	                out.write("HTTP/1.0 501 Not Implemented\r\n");
	                Date now = new Date();
	                out.write("Date: " + now + "\r\n");
	                out.write("Server: JHTTP 1.0\r\n");
	                out.write("Content-type: text/html\r\n\r\n"); 
	            }       
	            out.write("<HTML>\r\n");
	            out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n");
	            out.write("</HEAD>\r\n");
	            out.write("<BODY>");
	            out.write("<H1>HTTP Error 501: Not Implemented</H1>\r\n");
	            out.write("</BODY></HTML>\r\n");
	            out.flush();
	        }
	    }
	    catch (IOException ex)
	    {
	    }
	    finally
	    {
	    	try
	    	{
	    		connection.close();        
	    	}
	    	catch (IOException ex) {} 
	    }
    } // end run

	public static String guessContentTypeFromName(String name)
	{
	    if (name.endsWith(".html") || name.endsWith(".htm"))
	    {
	    	return "text/html";
	    }
	    else if (name.endsWith(".txt") || name.endsWith(".java")) 
	    {
	    	return "text/plain";
	    }
	    else if (name.endsWith(".gif"))
	    {
	    	return "image/gif";
	    }
	    else if (name.endsWith(".class"))
	    {
	    	return "application/octet-stream";
	    }
	    else if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
	    {
	    	return "image/jpeg";
	    }
	    else return "text/plain";
	}
}


以上只简单实现了GET方法,去获取服务器某个文件路径下的某个文件。这个http服务器的功能可以扩展到POST和DELETE方法,我们可以自行添加。

在Eclipse里面运行JHTTP类,启动这个服务器,控制台显示信息如下:

在本机上用命令行做试验:

回车后在命令行输入:
GET /index.html
就会显示服务器指定路径下的index.html文件的内容


参考资料:
《java Network Programming》 Elliotte Rusty Harold 著
  • 大小: 6 KB
  • 大小: 4.6 KB
  • 查看图片附件
发表评论
用户名: 匿名