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

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

1、请求报文

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

HTTP请求头

 

(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、结束该处理线程,处理其他客户请求;

程序代码如下:

[java]

  1. 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";  
        }  
              
    }

在该程序代码所在目录创建一个html页面,在浏览器地址栏输入http://localhost:8080/*.html,你会看到你所创建的页面。

转载于:https://my.oschina.net/fuluS/blog/310120

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值