计算机网路实验二 多线程Web服务器的设计与实现

计算机网路实验二 多线程Web服务器的设计与实现

一、 实验目的及任务
1、实验目的
熟悉简单网络的搭建与基本配置;
熟悉socket、多线程编程;
熟悉JDK编程工具的基本使用;
熟悉HTTP协议;
熟悉Web服务器的基本工作原理和配置。
2、实验任务
(1)以JDK为开发工具,利用Socket通信机制实现一个多线程的WEB服务器,该服务器具有以下功能:
 能够并行服务于多个请求。
 对于每个请求,显示接收到的HTTP请求报文的内容,并产生适当的响应(若找到用户请求对象,则返回该对象。否则发送一个包含适当提示信息的响应消息,从而可以在浏览器窗口中显示差错信息。)
(2)搭建一个简单的网络环境,调试 web服务器程序。
二、实验性质
设计性实验
三、 实验环境
操作系统:Windows2000 server
开发工具:JDK或其他开发工具
实验设备:交换机(一台)、计算机(两台)、网线若干

四、 实验步骤
1、 开发程序
2、 搭建简单的C/S网络
3、 配置并测试web服务器程序
五、 实验内容
1.Web服务器程序的结构框图如下:
在这里插入图片描述

2.实验源代码如下:

MultiTHreadWebServer.java

package networktwo;

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

HttpRequest.java
package networktwo;

import java.io.* ;
import java.net.* ;
import java.util.* ;
 
final class HttpRequest implements Runnable {
 //用”回车换行”作为Response消息头部行的结束
    final static String CRLF = "\r\n";
    Socket socket;
  //将参数socket即Socket connection赋给当前对象的(this)成员变量socket即this.socket
    public HttpRequest(Socket socket) throws Exception {
        this.socket=socket;
    }    
    
    public void run() {
	try {
		//调用实现Request消息处理绝大部分操作的方法
	    	processRequest();
		} catch (Exception e) {
			System.out.println(e);
		}
    }
 //实现Request消息处理
    private void processRequest() throws Exception {
    	InputStreamReader is=new InputStreamReader(socket.getInputStream());
        DataOutputStream os=new  DataOutputStream(socket.getOutputStream());
	    BufferedReader br = new BufferedReader(is);//往缓冲区读取(缓存)
 
        String  requestLine;
        //从输入流中读取字符,直到遇到CRLF为止
	    requestLine=br.readLine();
	    System.out.println(requestLine);
        //设置循环操作来获取Request消息的所有头部行
		String headerLine = null;
		while ((headerLine = br.readLine()).length() != 0) {
		        System.out.println(headerLine);
		}
 
		//Openfile,获取文件信息
        StringTokenizer tokens = new StringTokenizer(requestLine);
        tokens.nextToken();  //跳过请求方法
        String fileName = tokens.nextToken();//获取路径
        fileName="."+fileName;
	
        FileInputStream fis = null ;
        boolean fileExists = true ;
        try {
        	fis = new FileInputStream(fileName);
        } 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: " + contentType( fileName ) + 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>";
        }
        
        os.writeBytes(statusLine);
        os.writeBytes(contentTypeLine);
        os.writeBytes(CRLF);
        //如果文件存在调用另一个方法发送文件,不存在则向客户发送一个HTML编码的错误信息
        if (fileExists) {
        	sendBytes(fis, os);
	    fis.close();
        } else {
        	os.writeBytes(entityBody);
        }
        //关闭输入/出流和connection socket。 
        System.out.println();
        os.close();
        br.close();
        socket.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);
         }
    }
    //判断文件类型
    private static String contentType(String fileName) {
 
        if(fileName.endsWith(".htm") || fileName.endsWith(".html")|| fileName.endsWith(".txt")) {
               return "text/html";
        }
        if(fileName.endsWith(".jpg")) {
        	return "image/jpeg";
        }
        if(fileName.endsWith(".gif")) {
        	return "image/gif";
        }
        return "application/octet-stream";
 
    }
}

服务器的运行结果如下:
访问存在的文本文档:
在这里插入图片描述
在这里插入图片描述

访问已存在的图片文件如下:
在这里插入图片描述
在这里插入图片描述

访问不存在的文件:

在这里插入图片描述

  • 17
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值