java实现web服务器

java实现web服务器.txt明骚易躲,暗贱难防。佛祖曰:你俩就是大傻B!当白天又一次把黑夜按翻在床上的时候,太阳就出生了一个 Web 服务器也被称为 HTTP 服务器,它通过 HTTP 协议与客户端通信。这个客户端通常指的是 Web浏览器。一个基于Java的Web 服务器用到二个重要的类,java.net.Socket 与 java.net.ServerSocket ,并通过HTTP 消息通信。因此,本文从讨论 HTTP 与这二个类开始,然后我将解释一个与本文相关的简单的Web 应用。

The Hypertext Transfer Protocol(HTTP)

HTTP 是一种让 Web服务器与浏览器(客户端)通过Internet 发送与接收数据的协议。它是一个请求、响应协议--客户端发出一个请求,服务器响应这个请求。HTTP 运用可靠的 TCP 连接,通常用的TCP 80 端口。它的第一个版本是 HTTP/0.9 ,然后被HTTP/1.0取代。当前的版本是 HTTP/1.1 ,由 RFC2616(.pdf) 定义。

本节主要对应 HTTP 1.1 ,足够使你充分理解由Web服务器程序发出的消息。如果你对更加详细的知识有兴趣,可以参考 RFC2616 。

在HTTP 中,客户端总是通过建立一个连接与发送一个 HTTP 请求来发起一个事务。服务器不能主动去与客户端联系,也不能给客户端发出一个回叫连接。客户端与服务器端都可以提前中断一个连接。例如,当用一个浏览器下载一个文件时,你可以通过点击“停止”键来中断文件的下载,关闭与服务器的HTTP连接。

HTTP请求

一个HTTP 请求包含三个部分:

Method-URI-Protocol/Version 方法-地址-版本

Request header 请求头

Entity body 请求实体

下面是一个 HTTP请求实例:

POST /servlet/default.jsp HTTP/1.1

Accept: text/plain; text/html

Accept-Language: en-gb

Connection: Keep-Alive

Host:localhost

Referer: http://localhost/ch8/SendDetails.htm

User-Agent: Mozilla/4.0 (compatible;MSIE 4.01; Windows 98)

Content-Length: 33

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

LastName=Franks&FirstName=Michael

The Method-URI-Protocol/Version在这个请求的第一行:

POST /servlet/default.jsp HTTP/1.1

其中 POST是请求的类型。每个客户端 HTTP请求可以是 HTTP规范中指定的许多请求类型中的一种。HTTP1.1 支持七种类型的请求,它们是 GET,POST,HEAD,OPTIO NS,PUT,DELETE,TRACE。其中 GET 与 POST 是 Internet 应用中经常用到的二种请求类型。

URI 完整地指定了Internet资源。一个 URI 通常被解析为相对服务器的根目录。这样,它应该总是以一个 '/' 前缀开始。一个 URL 实际上是URI 的一种类型。

Version 指的是该 HTTP 请求所用到的 HTTP 协议版本。

请求头包含了客户端环境与请求实体的一些有用的信息。例如它包含浏览器设定的语言、实体的长度等等。每条请求头用回车换行符(CRLF)分开。

一个非常重要的空行分开了请求头与实体,它标志着实体内容的开始。一些 Internet开发书籍认为这个CRLF空行是 HTTP 请求的第四个部分。

在上面的 HTTP请求中,实体只是简单以下的一行:

LastName=Franks&FirstName=Michael

在一个典型的HTTP 请求中,请求实体内容会长得多。

HTTP响应

与请求相似,HTTP 响应也由三部分组成:

Protocol-Status code-Description 协议状态描述代码

Response headers 响应头

Entity body 响应实体

以下是一个HTTP 响应的实例:

HTTP/1.1200 OK

Server: Microsoft-IIS/4.0

Date: Mon, 3 Jan 1998 13:13:33 GMT

Content-Type:text/html

Last-Modified: Mon, 11 Jan 1998 13:23:42 GMT

Content-Length: 112

Welcome to Brainy Software

响应头的第一行类似请求头的第一行,告诉你所用的协议是HTTP 1.1 ,请求成功(200=success),以及没有任何问题。

响应头类似请求头也包含了一些有用的信息。响应的实体响应本身的 HTML 内容。头与实体之间由回车换行的空行(CRLF)分开。

Socket 类

一个 socket 是一个网络连接的端点,它使得一个应用可以从网络读与写。在不同电脑上的二个应用软件能够通过收发字节流而彼此通信。要发一个信息到另一个应用程序,你需要知道它的IP地址,以及它的socket端口号。在 Java 中,一个 socket用 jahttps://www.360docs.net/doc/9718567817.html,.Socket来实现。

要创建一个socket ,你可以用 Socket 类中几个构建方法中的一个。其中一个接受主机名与端口号作为参数:

newSocket("https://www.360docs.net/doc/9718567817.html,", 80);

一旦你成功地创建了一个 Socket类的实例,你就可以用它去发送与接收字节流了。要发送字节流,你需要呼叫Socket类的getOutputStream方法来得到一个java.io.OutputSteam 对象。要发送文本到远程的程序,你通常需要从返回的OutputSt ream 创建一个java.io.PrintWriter 对象。要从连接的另一端接收字节流,你需要呼叫 Socket 类的getInputStream 方法,它返回一个java.io.InputStream 对

象。

以下代码创建一个可以与本地HTTP 服务器通信的 socket (127.0.0.1 表示一个本地的主机),发送一个 HTTP 请求,并接收从服务器的响应。它还创建一个StringBuf fer对象来接受响应,并打印到控制台。

Socket socket = newSocket("127.0.0.1", "8080");

OutputStream os =socket.getOutputStream();

boolean autoflush = true;

PrintWriter out= newPrintWriter( socket.getOutputStream(),

autoflush );

BufferedReader in = new BufferedReader(

new InputStreamReader( socket.getInputStream() ));

// send an HTTP request to the web server

out.println("GET /index.jsp HTTP/1.1");

out.println("Host: localhost:8080");

out.println("Connection: Close");

out.println();

// read the response

boolean loop = true;

StringBuffer sb = new StringBuffer(8096);

while (loop) {

if ( in.ready() ) {

int i=0;

while (i!=-1) {

i =in.read();

sb.append((char) i);

}

loop = false;

}

Thread.currentThread().sleep(50);

// display the response to the out console

System.out.println(sb.toString());

socket.close();

注意要从 web 服务器得到正确的响应,你必须要发送用HTTP 协议编译了的 HTTP 请求。如果你看了上面的 HTTP 部分,你应该能够理解上面代码中的HTTP 请求。

编者注:这篇文章节选自 budi 自己出版的书。你可以在他的网站得到更多的相关资料。

基于Java的Web服务器工作原理2

作者:fajaven译发文时间:2003.09.12 17:00:38

ServerSocket 类

Socket类描述的是“客户端”socket,当你需要创建与远程服务程序连接时需要用到它。如果你想实现一个服务程序,如HTTP服务器或者FTP服务器,则需要另外不同的方法。这是因为你的服务器必须随时服务,它不知道什么时候会有一个客户端程序需要连接它。

因为这个目的,你需要用到 java.net.ServerSocket 这个类,它是服务器端 soc ket 的一个实现。服务器端socket 等待来自客户端的连接请求。一旦它收到一个连接请求,它创建一个 socket 实例来与客户端进行通信。

要创建服务器端socket ,需要用到ServerSocket 类提供的四个构建方法中的一个。你需要指定服务器端 socket侦听的IP 地址与端口号。比较典型地,这个IP 地址可以是 127.0.0.1 ,意思是该服务器端 socket侦听的是本地机器。服务器端 socket 侦听的 IP 地址指的是绑定地址。服务器端socket 另一个重要的属性是队列长度,即它拒绝请求前所接受的最大请求排队长度。

ServerSocket 类的构建方法之一如下:

public ServerSocket(int port,int backLog,InetAddress bindingAdd ress);

对于这个构建方法,绑定地址必须是 java.net.InetAddress 类的实例。创建一个InetAddress类的对象的简单方法是呼叫其静态方法getByName ,传递一个包含主机名的字符串。

InetAddress.getByName("127.0.0.1");

以下行的代码创建了一个服务器端socket ,它侦听本地机器的 8080端口,限制队列长度为 1 。

new ServerSocket(8080,1,InetAddress.getByName("127.0.0.1"));

一旦有了一个 ServerSocket 实例,就可以通过呼叫其accept 方法来让它等待进

来的链接请求。这个方法只有当接收到请求时才返回,它返回的是Socket 类的实例。这个Socket对象就可以用来从客户端应用程序发送与接收字节流,正如上节据说的那样。实际上,accept方法是本文例子中用到的唯一方法。

应用实例

我们的 web 服务器程序是 ex01.pyrmont包的一部分,它包含三个类:HttpServer;Request;Response。

整个程序的入口(静态 main 方法)是 HttpServer 类。它创建一个 HttpServer 的实例,并呼叫其await 方法。正如名字表达的,await 在一个特定的端口等待HTTP 请求,处理它们,并返回响应给客户端。它保持等待状态,直到收到停止命令。(用方法名 aw ait代替 wait ,是因为 System 中有一个重要的与线程相关的方法)

这个程序只从一个特定的目录发送静态资源,如 HTML与图像文件。它只支持没有文件头(如日期与 cookie)的情况。现在我们将在如下的几节中看一下这三个类。

HttpServer 类

HttpServer 实现了一个 web 服务器,它可以提供(serve)特定目录及其子目录下的静态资源。这个特定的目录由 public static final WEB_ROOT 指定。

WEB_ROOT初始化如下:

publicstatic final StringWEB_ROOT =

System.getProperty("user.dir") + File.separator +"webroot";

代码列表中包含了一具叫做 webroot 的目录,里面有一些静态的资源,你可以用来测试本应用。你也可以看到一个servlet ,在我的下一篇文章将会被用到:“Servlets 容器是怎样工作的”。

为了请求一个静态的资源,在浏览器的地址栏输入如是地址:http://machinename:port

/staticResources

如果你从不同的机器上发送请求到运行本应用的机器,则machinename 是运行应用机器的机器名或 IP 地址,port 是8080 ,staticResources是被请求的文件名称,它必须包含在 WEB_ROOT 目录内。

例如,如果你用同一台电脑来测试这个应用,你想要 HttpServer 发送index.html 这个文件,用以下的地址:http://localhost:8080/index.html

要停止服务,只需要从浏览器发送一个停止(shutdown)命令,即在浏览器的地址栏输入host:port 字段后,加上预先定义好的字符串。在我们的HttpServer 类中,停止命令被定义为 SHUTDOWN ,一个static final 变量。

private static final String SHUTDOWN_COMMAND ="/SHUTDOWN";

因此,要停止服务,你可以这样:http://localhost:8080/SHUTDOWN

现在,让我们看一下列表 1.1 中给出的await 方法。代码列表后面将对这段代码做一些解释。

Listing 1.1. The HttpServer class' awaitmethod

public void await() {

ServerSocket serverSocket = null;

int port = 8080;

try {

serverSocket = new ServerSocket(port, 1,

InetAddress.getByName("127.0.0.1"));

}

catch (IOException e) {

e.printStackTrace();

System.exit(1);

}

// Loop waitingfor a request

while (!shutdown) {

Socket socket = null;

InputStream input = null;

OutputStream output = null;

try {

socket = serverSocket.accept();

input = socket.getInputStream();

output = socket.getOutputStream();

// create Requestobject and parse Request request = new Request(input); request.parse();

// create Responseobject

Response response = newResponse(output);response.setRequest(request);

response.sendStaticResource();

相关主题
相关文档
最新文档