这里使用java socket和concurrent包里的ThreadPoolExecutor实现了一个小型的HTTP服务器,管理入站请求,代码如下:
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
分享到:
相关推荐
本项目"**NIO加线程池实现Android消息推送**"旨在通过Java NIO和线程池技术构建一个高效的推送系统,尤其适用于服务器需要处理大量并发连接的情况。 首先,我们来理解NIO(Non-blocking Input/Output)的概念。NIO...
当一个HTTP请求到达服务器,服务器会分配一个线程来处理这个请求,包括解析请求、执行业务逻辑、生成响应等。如果使用线程池模型,HTTP请求会被放入线程池的任务队列,等待空闲线程处理,这可以提高服务器的并发处理...
线程池模式是一种管理线程的技术,它预先创建了一组线程,当有新的任务需要执行时,线程池会从池中选择一个空闲线程来执行任务,而不是每次都创建新线程。这样可以减少线程创建和销毁的开销,提高系统响应速度。...
综上所述,Asynchronous-Server项目展示了如何使用Java的非阻塞I/O和自定义线程池来构建一个高效的异步服务器,以处理大规模并发网络连接。理解并掌握这些技术对于任何需要处理高并发问题的Java开发者来说都是至关...
在使用线程池下载大文件时,我们可以将文件分块,每个线程负责下载一个块。这样可以提高下载效率,同时在断点续传时也能轻松处理。线程间通过共享变量记录当前下载进度,确保各个线程协调工作。 在`Android人必看....
这个实验是一个很好的实践,它帮助我们理解操作系统如何通过线程池来高效地处理Web服务器的并发请求,同时也展示了Java并发编程在实际项目中的应用。通过分析和改进这个实验,我们可以深入理解操作系统、线程管理和...
在"MultithreadedServer"这个文件中,你可能找到一个简单的多线程HTTP服务器实现,它可能使用了Java的`java.net.ServerSocket`和`java.lang.Thread`类来监听连接和创建处理请求的线程。而"HttpServer"文件可能是一个...
当一个新任务提交时,线程池会分配一个空闲线程来执行任务,而不是每次都创建新的线程。这降低了创建和销毁线程的开销,提高了系统性能。在Java中,`java.util.concurrent`包下的`ExecutorService`和`...
在Java编程领域,构建一个简易的多线程HTTP服务器是一项常见的练习,这有助于理解网络通信、线程管理和HTTP协议的基本原理。在这个项目中,我们利用Java的线程池和Socket库来实现这样一个服务器,它支持GET、POST...
Java线程池的核心类`ThreadPoolExecutor`是`ExecutorService`接口的一个实现。它通过以下几个关键组件实现了线程池的基本功能: - **ExecutorService接口**:提供了任务提交和管理的基本方法。 - **...
例如,在Web服务器中,可以设置一个固定的线程池大小,以处理HTTP请求;在数据库访问层,可以采用具有动态调整能力的线程池,以应对不同时间段的负载变化。 总之,线程池作为现代软件架构中的重要组成部分,其设计...
线程池在IT行业中是一种非常重要的并发处理机制,特别是在服务器端编程中,它扮演着优化系统资源使用、提高系统响应速度的关键角色。本篇将深入探讨线程池、HTTP请求以及它们与服务器之间的关联。 首先,线程是操作...
### Java分布式应用学习笔记07线程池应用 在深入探讨Java分布式应用中线程池的应用之前,我们先来理解一下线程池的基本概念及其...因此,掌握线程池的设计原理和使用技巧,对于每一个Java开发人员来说都是非常必要的。
Java中的线程池实现通常基于工作队列,这是一个包含待处理任务的队列,由一组固定的线程进行处理。当线程从队列中取出任务并执行时,其他线程可以在队列空时等待新的任务到来。这种设计避免了调用者线程被阻塞的情况...
在IT行业中,网络请求是应用程序不可或缺的一部分,而`curl`作为一个强大的命令行工具,被广泛用于HTTP和其他协议的客户端操作。当我们需要处理大量的网络请求,尤其是进行数据抓取或者批量接口调用时,单线程的效率...
总结,本项目“基于Java线程池技术的数据爬虫设计与实现”旨在通过Java编程,利用线程池的优势,实现一个高效、稳定、可扩展的数据爬虫。这涵盖了多线程编程、网络通信、HTML解析、数据存储等多个IT领域的知识点,...
在本项目"JAVA实现知识问答服务器"中,我们将探讨如何使用Java编程语言构建一个能够处理问题与答案交互的服务器。这个服务器是针对初学者设计的,因此它将涵盖Java的基础概念,同时也为进阶学习者提供了实践平台。...
标题“webserver:java中的简单多线程Web服务器”指出,这是一个使用Java实现的Web服务器,它利用了多线程技术。多线程允许服务器同时处理多个客户端请求,提高了并发性能。每个客户端连接都会被分配到一个独立的线程...
线程池是多线程编程中的一个重要概念,它在Java、Python、C#等许多编程语言中都有广泛应用。线程池的出现是为了有效地管理和控制线程的创建与销毁,提高系统的资源利用率,防止过多线程导致系统资源耗尽。本文将深入...
综合以上,这个项目可能是一个实现Android应用与服务器通信的示例,利用线程池优化后台任务执行,采用单例模式管理网络请求,并通过WebService接口进行数据交换。理解并熟练掌握这些技术,对于提升Android开发能力...