实验二 多线程Web服务器的设计与实现

1、实验目的
熟悉简单网络的搭建与基本配置;
熟悉socket、多线程编程;
熟悉JDK编程工具的基本使用;
熟悉HTTP协议;
熟悉Web服务器的基本工作原理和配置。
2、实验任务
以JDK为开发工具,利用Socket通信机制实现一个多线程的WEB服务器,该服务器具有以下功能:
 能够并行服务于多个请求。
 对于每个请求,显示接收到的HTTP请求报文的内容,并产生适当的响应(若找到用户请求对象,则返回该对象。否则发送一个包含适当提示信息的响应消息,从而可以在浏览器窗口中显示差错信息。)
二、实验性质及学时
验证性实验,4学时
三、实验环境
与Internet连接的计算机网络系统;主机操作系统为Windows或Linux;
协议分析系统Wireshark。
四、实验报告内容(实验题目及答案,其中答案部分标红)

  1. Web服务器程序的结构框图如下:
    在这里插入图片描述
    源代码:
package webserver;

import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadWebServer {
    public static void main(String argv[]) throws Exception {
        //创建Web服务器的监听端口(套接字) TCP协议
        var socket = new ServerSocket(8189);
        while (true) {
            // 监听8189端口
            var connection = socket.accept();
            //创建httprequest对象,将标志着所建立TCP连接的Socket作为参数传递到它的构造函数中
            HttpServer request = new HttpServer(connection);
            //创建一个Thread对象,将HttpRequest对象作为参数传递给Thread的构造函数
            Thread thread = new Thread(request);
            //启动线程
            thread.start();
        }
    }

}

package webserver;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.net.Socket;

import java.util.Scanner;

public class HttpServer implements Runnable {
    final static String CRLF = "\r\n";//用”回车换行”作为Response消息头部行的结束 该符号为一行的判定标准
    Socket socket;

    //构造方法
    public HttpServer(Socket socket) {
        this.socket=socket;
    }
    //报文处理
    public void messageprocess() throws IOException {
      try(InputStreamReader inStream=new InputStreamReader(socket.getInputStream()); DataOutputStream outStream=new DataOutputStream(socket.getOutputStream())){
          //process input and send response
          BufferedReader br = new BufferedReader(inStream);//往缓冲区读取(缓存)

         //获取请求头
          String requestLine = br.readLine();
          System.out.println(requestLine);
          String headerLine = null;
          while ((headerLine = br.readLine()).length() != 0) {
              System.out.println(headerLine);
          }


          switch(requestLine){
              case "GET / HTTP/1.1":
                  get(br,outStream);
              case "POST / HTTP/1.1":
                  post(br,outStream);
              case "DELETE / HTTP/1.1":
                  del(outStream);
          }

      }catch (IOException e){
          e.printStackTrace();
      } catch (Exception e) {
          e.printStackTrace();
      }




    }
    //get方法处理
private void get(BufferedReader br,DataOutputStream outStream) throws Exception {
    FileInputStream fis = null ;
    boolean fileExists = true ;
    try {
        fis = new FileInputStream("F:/text/look.txt");
    } catch (FileNotFoundException e) {
        fileExists = false ;
    }

    // 分析客户Request消息的代码,并发送Response消息
    String statusLine = null;        //状态行
    String contentTypeLine = null;   //Content-Type行
    String entityBody = null;        //Entity body部分
    //请求文件存在生成头部行Content-type
    if (fileExists) {
        statusLine="HTTP/1.1 200 OK"+CRLF; //指示返回内容的类型
        contentTypeLine = "Content-type:text/html;charset=utf-8" + CRLF;

    } else {  //请求文件不存在生成状态行、头部行以及实体的主体,使用CRLF进行间隔
        statusLine="HTTP/1.1 404 NotFound"+CRLF;
        contentTypeLine = "Content-type: text/html"+CRLF;
        entityBody ="<html><title>Not found</title><h1>404 NotFound</h1></html>";
    }

    outStream.writeBytes(statusLine);
    outStream.writeBytes(contentTypeLine);
    outStream.writeBytes(CRLF);
    //如果文件存在调用另一个方法发送文件,不存在则向客户发送一个HTML编码的错误信息
    if (fileExists) {
        sendBytes(fis, outStream);
        fis.close();
    } else {
        outStream.writeBytes(entityBody);
    }
    //关闭输入/出流和connection
    System.out.println();
    outStream.close();


}
    private static void sendBytes(FileInputStream fis,OutputStream os) throws Exception {
        byte[] buffer = new byte[1024];//1KB
        int bytes=0;
        while((bytes=fis.read(buffer))!=-1){
            os.write(buffer,0,bytes);
        }
    }

    //post方法处理
    private void post(BufferedReader br,DataOutputStream outStream)throws IOException{
        char[] c=new char[1024];
        br.read(c);
       var str=new String(c);
       var sp=StringUtils.substringAfter(str, "name");
        System.out.println(sp);


        byte[] srtbyte = sp.getBytes();

        FileOutputStream fis = null ;
        boolean Exists = true ;
        try {
            fis = new FileOutputStream("F:/text/see.txt");
        } catch (FileNotFoundException e) {
            Exists = false ;
        }
        try {
             fis.write(srtbyte);
        }catch (Exception e){
            e.printStackTrace();
            Exists = false;
        }finally {
            fis.close();
        }


        // 分析客户Request消息的代码,并发送Response消息
        String statusLine = null;        //状态行
        String contentTypeLine = null;   //Content-Type行
        String entityBody = null;        //Entity body部分


        if (Exists) {
            statusLine="HTTP/1.1 200 OK"+CRLF; //指示返回内容的类型
            contentTypeLine = "Content-type:text/html;charset=utf-8" + CRLF;

        } else {  //请求文件不存在生成状态行、头部行以及实体的主体,使用CRLF进行间隔
            statusLine="HTTP/1.1 404 NotFound"+CRLF;
            contentTypeLine = "Content-type: text/html"+CRLF;
            entityBody ="<html><title>Not found</title><h1>404 NotFound</h1></html>";
        }

        outStream.writeBytes(statusLine);
        outStream.writeBytes(contentTypeLine);
        outStream.writeBytes(CRLF);
        //如果文件存在调用另一个方法发送文件,不存在则向客户发送一个HTML编码的错误信息

        //关闭输入/出流和connection socket。
        System.out.println();
        outStream.close();

    }

    //delete方法处理
    private void del(DataOutputStream outStream) throws IOException {
        FileOutputStream fis = null ;
        boolean Exists = true ;
        try {
            fis = new FileOutputStream("F:/text/look.txt");
        } catch (FileNotFoundException e) {
            Exists = false ;
        }
        try {
            fis.write(null);
        }catch (Exception e){
            Exists = false;
        }finally {
            fis.close();
        }


        // 分析客户Request消息的代码,并发送Response消息
        String statusLine = null;        //状态行
        String contentTypeLine = null;   //Content-Type行
        String entityBody = null;        //Entity body部分


        if (Exists) {
            statusLine="HTTP/1.1 200 OK"+CRLF; //指示返回内容的类型
            contentTypeLine = "Content-type:text/html;charset=utf-8" + CRLF;

        } else {  //请求文件不存在生成状态行、头部行以及实体的主体,使用CRLF进行间隔
            statusLine="HTTP/1.1 404 NotFound"+CRLF;
            contentTypeLine = "Content-type: text/html"+CRLF;
            entityBody ="<html><title>Not found</title><h1>404 NotFound</h1></html>";
        }

        outStream.writeBytes(statusLine);
        outStream.writeBytes(contentTypeLine);
        outStream.writeBytes(CRLF);
        //如果文件存在调用另一个方法发送文件,不存在则向客户发送一个HTML编码的错误信息

        //关闭输入/出流和connection socket。
        outStream.close();
    }
    @Override
    public void run() {
        try {
            messageprocess();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器的运行结果如下:
访问文档:
文件中的内容:
在这里插入图片描述
浏览器响应:
在这里插入图片描述
修改文档:发起post请求,修改文档:

文档中显示的结果:
在这里插入图片描述
清空文档:
发起delete请求

在这里插入图片描述
在这里插入图片描述
注:代码在运行的时候有问题会报错但并不会停止,可以完成HTTP这三种方法的操作。代码不完美,大家将就用。

  • 4
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值