douchuang

java编写一个多线程的简单Web服务器

根据http协议的会话过程,实验实现了GET请求的web服务器的方法:

通过创建ServerSocket类对象。侦听用户指定端口,等待并接受客户机请求到端口。创建与Socket相关联的输入流输出流,然后读取客户机的请求信息。若请求类型为GET,则从请求信息中获取所访问的HTML文件名:如果文件存在,则打开,把HTML头信息和文件内容通过Socket传回给浏览器,然后关闭,否则发送错误提示。

1.主线程设计:

主线程的设计就是在主线程httpserver类中实现了服务器端口的侦听,服务器接受一个客户端请求之后创建一个线程实例处理请求:主要代码:

public static void main(String args[]) {

      //端口信息

      int port;

      ServerSocket server_socket;

      //读取服务器端口号

      try {

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

      }

      catch (Exception e) {

         //为默认端口

         port = 8888;

      }

      try {

         //监听服务器端口,等待连接请求

         server_socket = new ServerSocket(port);

         System.out.println("httpServer running on port " +

            server_socket.getLocalPort());

         //显示启动信息

         while(true) {

            //服务器接收线程

            Socket socket = server_socket.accept();

            System.out.println("New connection accepted " +

                socket.getInetAddress() +

                ":" + socket.getPort());

2.连接处理分线程设计

在分线程httpRequestHandler类中实现了http的处理,以下代码中设计的类实现了Runnable接口。

class httpRequestHandler implements Runnable {

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

   Socket socket;//套接字获得

   InputStream input;//输入流

   OutputStream output;//输出流

   BufferedReader br;

   //构造方法

   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()));

   }

   //实现Runnable 接口的run()方法

   public void run(){

      try {

         processRequest();

      }

      catch(Exception e) {

         //打印错误信息

         System.out.println(e);

      }

   }

3.构建processRequest()方法来处理信息的接受与发送

代码实现了Runnable接口的主要内容,在run()方法中调用processRequest()方法来处理客户请求的接受和服务器返回信息的发送。

private void processRequest() throws Exception {

      while(true) {

         //读取并显示Web 浏览器提交的请求信息

         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 ;

            fileName ="C:/Inetpub/wwwroot"+fileName;

            //打开所请求的文件

            FileInputStream fis = null;

            boolean fileExists = true

在processRequest()方法中得到客户端请求后,利用一个StringTokenizer类完成了字符串的拆分,这个类可以根据字符串指定的分隔符将字符串拆分为字串的功能。利用nextToken()方法依次得到这些字串,sendBytes()方法完成信息内容的发送,contentType()用于判断文件类型。

4。测试程序:创建一个html格式的网页,名字为index.html存入默认的文件路径下。运行java程序,程序显示指定端口打开后,在浏览器输入http://localhost:指定端口(本程序8888)/index.html,看是否可以正确显示网页。

5.程序完整代码以及运行测试结果:

import java.net.*;
import java.io.*;
import java.util.*;
public class httpServer{
    public static void main(String args[]) {
        //端口信息
        int port;
        ServerSocket server_socket;
        //读取服务器端口号
        try {
            port = Integer.parseInt(args[0]);
        }
        catch (Exception e) {
            //为默认端口
            port = 8888;
        }
        try {
            //监听服务器端口,等待连接请求
            server_socket = new ServerSocket(port);
            System.out.println("httpServer 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;
    //构造方法
    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()));
    }
    //实现Runnable 接口的run()方法
    public void run(){
        try {
            processRequest();
        }
        catch(Exception e) {
            //打印错误信息
            System.out.println(e);
        }
    }
    private void processRequest() throws Exception {
        while(true) {
            //读取并显示Web 浏览器提交的请求信息
            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 ;
                fileName ="C:/Inetpub/wwwroot"+fileName;
                //打开所请求的文件
                FileInputStream fis = null;
                boolean fileExists = true;                
                try    {                
                    fis = new FileInputStream(fileName);//文件输出流                    
                }
                catch(FileNotFoundException e) {
                    fileExists = false;                    
                    System.err.println("file not found :"+fileName);
                }
                //完成回应消息
                String serverLine = "Server: a simple java httpServer";
                String statusLine = null;//状态行信息
                String contentTypeLine = null;//内容类型行
                String entityBody = null;
                String contentLengthLine = "error";
                if(fileExists) {
                    statusLine = "HTTP/1.0 200 OK" + CRLF ;
                    contentTypeLine = "Content-type: " +
                        contentType( fileName ) + CRLF ;
                    contentLengthLine = "Content-Length: "
                        + (new Integer(fis.available())).toString()
                        + CRLF;
                }
                else {
                    statusLine = "HTTP/1.0 404 Not Found" + CRLF ;
                    contentTypeLine = "text/html" ;
                    entityBody = "<HTML>" +
                        "<HEAD><TITLE>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)    {
                    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 {
        // 创建一个 1K buffer
        byte[] buffer = new byte[1024] ;
        int bytes = 0 ;
        // 将文件输出到套接字输出流中
        while ((bytes = fis.read(buffer)) != -1 ) {
            os.write(buffer, 0, bytes);//通过写缓冲的方式
        }
    }
    private static String contentType(String fileName) {
        if (fileName.endsWith(".htm") || 
                fileName.endsWith(".html"))    {
            return "text/html";
        }        
        return "fileName";//返回文件名
    }
}  

java程序运行结果:

打开浏览器输入网址:

此时java控制台显示

分类:

技术点:

相关文章:

  • 2021-12-27
  • 2021-12-17
  • 2021-11-03
  • 2021-11-23
  • 2021-12-17
  • 2021-12-17
  • 2021-12-17
  • 2021-11-07
猜你喜欢
  • 2021-11-23
  • 2021-11-15
  • 2021-12-17
  • 2021-12-27
  • 2021-12-03
相关资源
相似解决方案