分享
 
 
 

用java实现的一个简单web服务器程序

王朝学院·作者佚名  2009-12-02
窄屏简体版  字體: |||超大  

一、首先来看一下http的报文结构

1、请求报文

一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,下图给出了请求报文的一般格式。

(1)请求行

请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。

HTTP协议的请求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。这里介绍最常用的GET方法和POST方法。

GET:当客户端要从服务器中读取文档时,使用GET方法。GET方法要求服务器将URL定位的资源放在响应报文的数据部分,回送给客户端。使用GET方法时,请求参数和对应的值附加在URL后面,利用一个问号(“?”)代表URL的结尾与请求参数的开始,传递参数长度受限制。例如,/index.jsp?id=100&op=bind。

POST:当客户端给服务器提供信息较多时可以使用POST方法。POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据。

(2)请求头部

请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。请求头部通知服务器有关于客户端请求的信息,典型的请求头有:

User-Agent:产生请求的浏览器类型。

Accept:客户端可识别的内容类型列表。

Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。

(3)空行

最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。

(4)请求数据

请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。

2、响应报文

响应报文的格式大体上和请求报文类似,只是第一行有所不同,读者可以自己在网上查找这方面的介绍,这里不再赘述。

二、程序的实现

程序的实现步骤如下:

1、接收客户端浏览器的请求;

2、创建一个新的线程,用于处理该次请求;

3、读取报文数据,判断报文正确与否,分析报文内容;

4、创建响应报文,发送到客户端;

5、结束该处理线程,处理其他客户请求;

程序代码如下:

view plaincopy to clipboardprint?

import java.net.*;

import java.io.*;

import java.util.*;

import java.lang.*;

public class WebServer {

public static void main(String [] args){

int port;

ServerSocket server_socket;

try{

port=Integer.parseInt(args[0]);

}

catch (Exception e){

port=8080;

}

try{

server_socket=new ServerSocket(port);

System.out.println("WebServer running on port"+server_socket.getLocalPort());

while(true){

Socket socket=server_socket.accept();

System.out.println("New connection accepted"+socket.getInetAddress()+":"+socket.getPort());

//针对特定的请求创建处理该请求的线程

try{

httpRequestHandler request=new httpRequestHandler(socket);

Thread thread=new Thread(request);

thread.start();

}

catch(Exception e){

System.out.println(e);

}

}

}

catch(IOException e){

System.out.println(e);

}

}

}

//处理请求的线程类

class httpRequestHandler implements Runnable{

final static String CRLF="\r\n";

Socket socket;

InputStream input;

OutputStream output;

BufferedReader br;

//判断请求的文件类型是否正确

boolean fileType=true;

//初始化参数

public httpRequestHandler(Socket socket) throws Exception{

this.socket=socket;

this.input=socket.getInputStream();

this.output=socket.getOutputStream();

this.br=new BufferedReader(new InputStreamReader(socket.getInputStream()));

}

//启动该线程

public void run(){

try{

processRequest();

}

catch(Exception e){

System.out.println(e);

}

}

//处理请求的核心函数

private void processRequest() throws Exception{

while(true){

String headerLine=br.readLine();

System.out.println("the client request is"+headerLine);

if(headerLine.equals(CRLF)||headerLine.equals(""))

break;

StringTokenizer s=new StringTokenizer(headerLine);

String temp=s.nextToken();

if(temp.equals("GET")){

String fileName=s.nextToken();

fileName="."+fileName;

FileInputStream fis=null;

boolean fileExists=true;

if(!(fileName.endsWith(".htm")||fileName.endsWith(".html")))

{

this.fileType=false;

try{

fis=new FileInputStream("error.html");

}

catch(FileNotFoundException e){

fileExists=false;

}

}

else{

try{

fis=new FileInputStream(fileName);

}

catch(FileNotFoundException e){

fileExists=false;

}

}

String serverLine="Server:a simple java WebServer";

String statusLine=null;

String contentTypeLine=null;

String entityBody=null;

String contentLengthLine="error";

if(fileExists&&this.fileType){

statusLine="HTTP/1.0 200 OK"+CRLF;

contentTypeLine="Content-type:"+this.contentType(fileName)+CRLF;

contentLengthLine="Content-Length:"+(new Integer(fis.available())).toString()+CRLF;

}

else{

if(fileExists&&this.fileType==false){

statusLine="HTTP/1.0 400 BadRequest"+CRLF;

contentTypeLine="text/html";

entityBody="<HTML>400 Not BadRequest</TITLE></HEAD>"+

"<BODY>400 BadRequest"+

"<br>usage:http://yourHostName:port/"+

"fileName.html</BODY></HTML>";

}

else if(fileExists==false){

statusLine="HTTP/1.0 404 Not Found"+CRLF;

contentTypeLine="text/html";

entityBody="<HTML>404 Not Found</TITLE></HEAD>"+

"<BODY>404 Not Found"+

"<br>usage:http://yourHostName:port/"+

"fileName.html</BODY></HTML>";

}

}

output.write(statusLine.getBytes());

output.write(serverLine.getBytes());

output.write(contentTypeLine.getBytes());

output.write(contentLengthLine.getBytes());

output.write(CRLF.getBytes());

if(fileExists&&this.fileType){

sendBytes(fis,output);

fis.close();

}

else{

output.write(entityBody.getBytes());

}

}

}

try{

output.close();

br.close();

socket.close();

}

catch(Exception e){}

}

//将客户端请求的页面发送出去

private static void sendBytes(FileInputStream fis,OutputStream os) throws Exception{

byte[] buffer=new byte[1024];

int bytes=0;

while((bytes=fis.read(buffer))!=-1){

os.write(buffer,0,bytes);

}

}

//设置contentType的内容

private static String contentType(String fileName){

if(fileName.endsWith(".htm")||fileName.endsWith(".html")){

return "text/html";

}

return "fileName";

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有