首页 > 学院 > 开发设计 > 正文

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

2019-11-17 04:00:26
字体:
来源:转载
供稿:网友
一、首先来看一下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";   
    }   
           
}  
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表