精华内容
下载资源
问答
  • 简单web服务器的设计与实现

    万次阅读 2017-01-27 19:48:09
    socket web服务器

    一、综合训练目的与要求

    运用数据通信及网络课程所学的知识,设计一个简单的http服务器,在实现的过程中学习网络套接字编程、HTTP 协议、Web 服务器等知识;提供静态网页浏览服务功能;Web 服务器可配置参数有主目录、首页文件名、HTTP 端口号等项,锻炼UNIX环境下网络编程的能力,熟悉socket编程原理和http协议,从而巩固所学网络知识。

    二、综合训练任务

    1)要能实现get方法;

    2)能响应请求的html页面;

    3)还能够响应请求的gif,jpg的等图片文件;

    4)能响应请求的目录的信息,并以列表显示;

    5) 能读取文本文件txt。

     

    三、总体设计

    3.1 工作原理

     

         网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用叫Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用,数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 

    Linux网络编程中常用的系统调用函数包括:初始化(socket)、连接(connect)、绑定(bind)、监听(1isten)、接收(accept)、关闭(close)、发送(send)。 

    Socket接口通过以下函数为应用编程提供服务: 1)socket():创建一个套接字; 

    2) bind():用于将套接字与本地或远程某个地址和端口建立关联; 3) listen():用于在服务器一端监听是否有连接请求; 4) connect():客户通过调用该函数主动与服务器建立连接; 5) accept():用于接收来自客户的连接请求,服务器先创建一个新的套接字,用新套接字与客户进行通信,原套接字仍保持侦听状态,以便接收其他连接请求;6)send()和recv():SOCK_STREAM类型套接字数据的发送和接收; 7) close():关闭套接字。

     HTTP协议是基于请求/响应模式的。一个客户机与服务器建立连接后,发送一个请求给服务器。服务器接到请求后,给予相应的响应信息。在Internet上,HTTP通信通常发生在TCP/IP连接之上,建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息:包括请求修饰符、客户机信息和可能的内容服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容,客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客http工作流程图户机与服务器断开连接。 

    基于HTTP协议的客户/服务器模式的信息交换分四个步骤:建立连接、发送请求信息、发送响应信息和关闭连接

     

    3.2设计过程

     

    Web服务器的工作方式都是以套接字机制为基础的。对于一个B/S通信模型,在服务器端,首先创建一个套接字,并将此套接字与服务器公认的IP地址绑定在一起,接着将套接字转换成侦听套接字来侦听用户的请求,在接收到客户机的请求后就建立连接,然后服务器和客户机之间就可以进行通信了。多个请求时服务器使用不同的进程来

    进行处理,互不干扰。以下为web服务器的工作流程图:

     


    四、详细设计说明

    1、服务器端 

    1)创建一个socket; 

    2)将该socket与本机地址/端口号捆绑; 

    3)在监听端口上监听客户机的连接请求; 

    4) 当accept捕捉到一个连接请求时,就建立连接线路并返回一个新的通信文件描述符; 

    5)父进程创建一个子进程,父进程关闭通信文件描述符并继续监听端口上其它客户机的连接请求; 

    6)子进程通过通信文件描述符与客户机进行通信,通信结束后终止子进程并关闭通信文件描述符。

     

    2、浏览器端

    1)创建一个socket; 

    2)向指定的服务器主机及端口发出连接请求,请求成功将返回通信文件描述符;

    3)调用connect函数与服务器建立连接;

    4)连接成功之后与服务器进行通信:

    ①、建立子进程;

    ②、处理get方式请求的静态网页;

    ③、接收请求

    ④、执行相关程序(CGI,sh)

    ⑤、回应请求

    5)通信完毕后关闭通信文件描述符。


    五、实习总结

    本次Linux综合实训,这次我们成功实现了一个小型的http服务器,能访问我们自己的网页;其次,在实现http服务器的过程中,熟悉了http协议等网络相关知识,巩固并实践了上学期网络课程所学内容;还有,我们又锻炼了UNIX环境下编程开发能力,基本了解了Web服务器的设计和工作原理,更加深了对socket套接字建立服务器端的过程,掌握了一些Linux下c语言网络编程方法,更加深了我对书本知识的理解。

        遇到的最大问题:实现CGI接口时,CGI无法获取到测试网页表单中的参数,表单提交后找不到路径,直接跳到404页面。原因是表单提交请求方式是get,get请求方式的参数显示在地址栏上文件后缀名之后,服务器没有匹配到文件类型字符串,故无法找到页面。


    六、核心代码

    1、socket服务器端

     

    intmake_server_socket_q(int,int);

     

     

    intmake_server_socket(int protnum)

    {

        returnmake_server_socket_q(protnum,BACKLOG);

    }

     

     

     

    intmake_server_socket_q(int portnum,int backlog)

    {

        struct sockaddr_in saddr;

        //创建服务器socket

        intsock_id;

      

     

        sock_id=socket(PF_INET, SOCK_STREAM, 0);

     

        if(sock_id==-1)//失败

        {

            return -1;

        }

        bzero((void *)&saddr,sizeof(saddr));

        saddr.sin_addr.s_addr=htonl(INADDR_ANY);

        saddr.sin_port=htons(portnum);

        saddr.sin_family=AF_INET;

        //绑定

        if(bind(sock_id,(struct sockaddr*)&saddr,sizeof(saddr))!=0)

            return -1;

        //监听

        if(listen(sock_id,backlog)!=0)

            return -1;

        return sock_id;

     

    }

     

     

     

    intconnect_to_server(char *host,int portnum)

    {

        int sock;

        struct sockaddr_in servadd;//the number tocall

        struct hostent *hp;//used to get number

        //

        sock = socket(PF_INET,SOCK_STREAM,0);//geta line

        if(sock==-1)

            return -1;

        //清空

        bzero(&servadd,sizeof(servadd));

        hp = gethostbyname(host);

        if(hp==NULL)

            return -1;

        bcopy( hp->h_addr,(structsockaddr*)&servadd.sin_addr, hp->h_length);

        // servadd.sin_addr=htonl(INADDE_ANY);

        servadd.sin_port=htons(portnum);

        servadd.sin_family=AF_INET;

        if(connect(sock,(structsockaddr*)&servadd,sizeof(servadd))!=0)

            return -1;

        return sock;

    }

     

    2、浏览器端

     

    main(intac,char*av[])

    {

        //socket描述符和accept描述符

        int sock,fd;

        FILE *fpin;

        //保存请求

        char request[BUFSIZ];

        if(ac==1)

        {

            fprintf(stderr,"usage:wsportnum\n");

            exit(1);

        }

        sock=make_server_socket(atoi(av[1]));//atoi方法将字符串变成整型

        if(sock==-1) exit(2);

     

        while(1)

        {

            //该函数会阻塞等待客户端请求到达

            fd =accept(sock,NULL,NULL);

            //只读方式接收请求(文件流)

            fpin=fdopen(fd,"r");

            //得到请求

            fgets(request,BUFSIZ,fpin);

            //打印到控制台请求记录

            printf("got a call :request =%s",request);

               read_til_crnl(fpin);

            //处理请求

            process_rq(request,fd);

            //结束本次请求

            fclose(fpin);

        }

    }

     

     

     

    //读取完整的请求

    read_til_crnl(FILE*fp)

    {

        char buf[BUFSIZ];

       while(fgets(buf,BUFSIZ,fp)!=NULL&&strcmp(buf,"\r\n")!=0);

    }

     

     

    //处理请求

    process_rq(char*rq, int fd)

    {

        char cmd[BUFSIZ],arg[BUFSIZ];

        //创建子进程,如果不是子进程则结束

        if (fork()!=0)

            return;

        strcpy(arg,"./");

        if(sscanf(rq,"%s%s",cmd,arg+2)!=2)

            return;

        if(strcmp(cmd,"GET")!=0)//只能处理静态网页get方式

            cannot_do(fd);

        else if (not_exist(arg))//请求出错

            do_404(arg,fd);

        else if (isadir(arg))//判断是否为目录

            do_ls(arg,fd);

        else if (ends_in_cgi(arg))//是否为cgi程序

            do_exec(arg,fd);

        else if (ends_in_sh(arg))//是否为sh程序

            do_exec_sh(arg,fd);

        else

            do_cat(arg,fd);

    }

     

     

    //获取头部信息

    header(FILE*fp,char*content_type)

    {

        fprintf(fp,"HTTP/1.0 200OK\r\n");

        if(content_type)

            fprintf(fp,"Content-type:%s\r\n",content_type);

    }

     

    //请求501错误

    cannot_do(intfd)

    {

        FILE *fp =fdopen(fd,"w");

     

           fprintf(fp,"HTTP/1.0 501 NotImplemented\r\n");

       fprintf(fp,"Content-type:text/plain\r\n");

        fprintf(fp,"\r\n");

        fprintf(fp,"Sorry,HTTP 501!\n\n无法处理请求!");

        fclose(fp);

     

    }

     

     

    //请求出错404

    do_404(char*item,int fd)

    {

        FILE *fp=fdopen(fd,"w");

     

        fprintf(fp,"HTTP/1.0 404 NotFound\r\n");

       fprintf(fp,"Content-type:text/plain\r\n");

        fprintf(fp,"\r\n");

        fprintf(fp,"Sorry,HTTP 404!\n\nTheitem you requested: %s \r\nis not found\r\n",item);

        fclose(fp);

    }

     

     

    //判断是否为目录

    isadir(char*f)

    {

        struct stat info;

        return(stat(f,&info)!=-1&&S_ISDIR(info.st_mode));

     

    }

     

     

    //不存在

    not_exist(char*f)

    {

        struct stat info;

        return (stat(f,&info)==-1);

    }

     

     

    //显示目录下内容

    do_ls(char*dir,intfd)

    {

        FILE *fp;

     

        fp = fdopen(fd,"w");

       header(fp,"text/plain;charset=UTF-8");

        fprintf(fp,"\r\n");

        fflush(fp);

     

        dup2(fd,1);

        dup2(fd,2);

        close(fd);

       execlp("ls","ls","-l",dir,NULL);

        perror(dir);

        exit(1);

    }

     

     

    //返回文件类型

    char*file_type(char *f)//return 'extension' of file

    {

        char *cp;

        if((cp=strrchr(f,'.'))!=NULL)

            return cp+1;

        return " ";

    }

     

    //cgi类型文件

    ends_in_cgi(char*f)

    {

       return(strcmp(file_type(f),"cgi")==0);

    }

     

     

     

    //执行shell程序

    ends_in_sh(char*f)

    {

       return(strcmp(file_type(f),"sh")==0);

    }

     

    do_exec_sh(char*prog,int fd)

    {

        system(prog);

    }//shell

     

     

    //执行可执行程序cgi

    do_exec(char*prog,int fd)

    {

        FILE *fp;

        fp =fdopen(fd,"w");

        header(fp,NULL);

        fflush(fp);

       

        dup2(fd,1);

        dup2(fd,2);

        close(fd);

        execl(prog,prog,NULL);

        perror(prog);

       

    }



    展开全文
  • 简单的web服务器 计算机网络实验 多线程Web服务器的设计与实现
  • 计算机网路实验二 多线程Web服务器的设计与实现 一、 实验目的及任务 1、实验目的 熟悉简单网络的搭建与基本配置; 熟悉socket、多线程编程; 熟悉JDK编程工具的基本使用; 熟悉HTTP协议; 熟悉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";
     
        }
    }
    

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

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

    访问不存在的文件:

    在这里插入图片描述

    展开全文
  • 设计了一种基于LwIP协议嵌入式设备Web服务器。利用网页就可以配置嵌入式设备内部参数及程序升级。充分利用STM32平台内部集成以太网模块和LwIP轻型网络协议栈特点,通过以太网物理层芯片LAN8720和RJ45接口相连,...
  • 2、 网络服务器基本配置(简单C/S网络的组建、web服务器的基本配置等) 3、程序设计(socket编程、多线程程序设计等) JAVA代码: MultiThreadWebServer.java import java.net.* ; public final class Multi

    内容相关:

    1、 网络基本原理(如:HTTP协议、Web服务器、SocketTCPUDP等)

    2、 网络服务器基本配置(简单C/S网络的组建、web服务器的基本配置等)

    3、程序设计(socket编程、多线程程序设计等)

    JAVA代码:

    MultiThreadWebServer.java

    import java.net.* ;
    
    public final class MultiThreadWebServer {
        public static void main(String argv[]) throws Exception {
        	
        	ServerSocket socket = new ServerSocket(8900);
            while (true) {
    	    // Listen for a TCP connection request.
    	    Socket connection = socket.accept();
    
    	    HttpRequest request = new HttpRequest(connection);
    	    
    	    Thread thread = new Thread(request);
    
    	    thread.start();
            }
        }
    }

    HttpRequest.java

    import java.io.* ;
    import java.net.* ;
    import java.util.* ;
    
    final class HttpRequest implements Runnable {
    
        final static String CRLF = "\r\n";
        Socket socket;
        
        public HttpRequest(Socket socket) throws Exception {
            this.socket=socket;
        }    
        
        public void run() {
    	try {
    	    	processRequest();
    		} catch (Exception e) {
    			System.out.println(e);
    		}
        }
    
        private void processRequest() throws Exception {
        	InputStreamReader is=new InputStreamReader(socket.getInputStream());
            DataOutputStream os=new  DataOutputStream(socket.getOutputStream());
    	    BufferedReader br = new BufferedReader(is);
    
            String  requestLine;
    	    requestLine=br.readLine();
    	    System.out.println(requestLine);
    
    		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 ;
            }
    
            // Reponse
            String statusLine = null;        //状态行
            String contentTypeLine = null;   //Content-Type行
            String entityBody = null;        //Entity body部分
            if (fileExists) {
            	statusLine="HTTP/1.1 200 OK"+CRLF;
            	contentTypeLine = "Content-type: " + contentType( fileName ) + CRLF;
                  
            } else {
            	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);
            if (fileExists) {
            	sendBytes(fis, os);
    	    fis.close();
            } else {
            	os.writeBytes(entityBody);
            }
            System.out.println();
            os.close();
            br.close();
            socket.close();
            
        }
    
        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);
             }
        }
        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";
    
        }
    }
    结果展示:



    PYTHON代码(请在python3下运行):

    import socket
    import re
    import threading
    import time
    CRLF = "\r\n"
    contentTypeLine="Content-type:";
    def server(conn,addr):
        data = conn.recv(2048)
        print(data)
        print("-----------\n")
        
        f = data.decode('utf-8').split(' ')[1]
        try:
            x=open('.'+f,"rb").read()
            conn.send(bytearray("HTTP/1.1 200 OK"+CRLF,'utf8'))
            conn.send(bytearray(contentTypeLine+webtype(f)+CRLF,'utf8'))
            conn.send(bytearray("Date:"+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +CRLF,'utf8'))
            conn.send(bytearray(CRLF,'utf8'))
            conn.send(x)
            except IOError:
            conn.send(bytearray("HTTP/1.1 404 NotFound"+CRLF,'utf8'))
            conn.send(bytearray(contentTypeLine+"text/html"+CRLF,'utf8'))
            conn.send(bytearray("Date:"+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) +CRLF,'utf8'))
            conn.send(bytearray(CRLF,'utf8'))
            conn.send(bytes("<h1>404</h1>",'utf8'))
        
        conn.close()
    def webtype(filename):
        a=filename.split('.')[1]
        if a == 'txt':
            return 'text/html'
        if a == 'jpg':
            return 'image/jpeg'
        return "other type"
    if __name__ =='__main__':
        ip_port = ('127.0.0.1',8888) 
        web = socket.socket() 
        web.bind(ip_port)
        web.listen(5) 
        print ('opening...PORT:8888') 
        while True:
            conn,addr = web.accept()  
            thread = threading.Thread(target=server, args=(conn, addr))
            thread.start()
    

    结果与上图类似,不上图了。


    展开全文
  • 摘要:设计实现了基于SOPC技术的嵌入式Web服务器,简单介绍了SOPC技术的特点及构建方法,随后对该嵌入式Web服务器的实现在硬件和软件两方面都作了详细论述,其中运用Nios II软核处理器作为主控制器,实时多任务...
  • 此次是分布式第三次作业,作业要求如下: 1、基于TCP通讯(ServerSocket、...2、在此基础上,修改服务器设计与实现,使之能够动态地添加客户端请求类文件,即设计 一个小服务程序容器。 3、试在服务器侧代码

    此次是分布式的第三次作业,作业要求如下:

    1、基于TCP通讯(ServerSocket、Socket套接字),编写一个带有图形用户界面的浏览器和

    一个支持文档读取并返回给客户浏览器的web服务器。客户端支持超链接事件处理,服务器采用多

    线程技术支持并发访问。

    2、在此基础上,修改服务器侧设计与实现,使之能够动态地添加客户端请求的类文件,即设计

    一个小服务程序容器。

    3、试在服务器侧代码中对客户端请求行、请求头和请求体部分进行处理。

    ====================================================================分割线

    没有完成第3个要求。


    客户端有两个类,一个是主类Client.java,
    一个是浏览器类Browser.java。
    Client.java代码如下:
    package com.client;
    
    import java.io.IOException;
    
    public class Client {
    
    	public static  String request;
    	public static void main(String[] args) throws IOException{
    			
    		Browser browser = new Browser();	//生成浏览器对象
    		browser.setBrowser();				//调用setBrowser()方法初始化浏览器
    	}
    }
    

    Browser.java的代码如下:
    package com.client;
    
    import java.awt.Button;
    import java.awt.Frame;
    import java.awt.TextField;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.io.*;
    import java.net.Socket;
    import javax.swing.*;
    import javax.swing.event.HyperlinkEvent;
    import javax.swing.event.HyperlinkListener;
    
    @SuppressWarnings("serial")
    public class Browser extends Frame implements HyperlinkListener {
    
    	JEditorPane jEditorPane = new JEditorPane();//浏览器显示框
    	String request = null;	//定义字符串保存用户输入的请求
    	
    	//初始化浏览器框
    	public void setBrowser() throws IOException {
    
    		JFrame frame = new JFrame("浏览器");
    		frame.setSize(800, 600);
    		frame.setLocation(100, 50);
    		frame.setLayout(null);
    		frame.setResizable(false);
    
    		jEditorPane.setEditable(false);
    		jEditorPane.setContentType("text/html");//设置显示框的文本类型,使可以显示html
    		JScrollPane jScrollPane = new JScrollPane(jEditorPane);//加一个滑动框
    		jScrollPane.setSize(200, 200);
    		jScrollPane.setLocation(100, 100);
    		jScrollPane.setBounds(50, 100, 700, 450);
    		jEditorPane.addHyperlinkListener(this);//添加超链接监听
    		
    		TextField textField = new TextField(50);
    		textField.setBounds(200, 50, 320, 30);
    		textField.setText("http://127.0.0.1:8080/");//初始化的时候添加访问地址和端口,不用重复输入
    		Button button = new Button("前往");
    		button.setBounds(550, 50, 70, 30);
    
    		frame.add(textField);
    		frame.add(button);
    		frame.add(jScrollPane);
    
    		myActionListener myActionListener = new myActionListener(textField);
    		button.addActionListener(myActionListener);//在button上添加监听
    
    		//给主frame上添加关闭按钮的功能
    		frame.addWindowListener(new WindowAdapter() {
    			public void windowClosing(WindowEvent e) {
    				// TODO Auto-generated method stub
    				System.exit(0);
    			}
    		});
    		
    		frame.setVisible(true);//设置可见
    	}
    	
    	//处理文JEditPane中的超链接
    	public void hyperlinkUpdate(HyperlinkEvent e){
    		try{
    			if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED){
    				jEditorPane.setPage(e.getURL());	//setPage方法可以直接获取连接内容
    			}
    		} catch (IOException e1) {
    			
    			e1.printStackTrace();
    		}
    	}
    	
    	//自定义监听类实现ActionListener接口
    	class myActionListener implements ActionListener{
    
    		TextField textField = new TextField();
    		//将textField对象传进来,用以取用户的输入内容
    		public myActionListener(TextField textField) {
    			
    			this.textField = textField;//获取到用户请求的url地址
    		}
    		
    		//actionPerformed方法用以处理请求
    		public void actionPerformed(ActionEvent e){
    		
    			//简单处理请求的url,将其处理成http请求行的样子 
    			String url = textField.getText();
    			
    			url.trim();			//去掉空格
    			int beginindex = url.indexOf("//");
    			url = url.substring(beginindex+2, url.length());
    			beginindex = url.indexOf("/");
    			url = url.substring(beginindex, url.length());
    			request = "POST " + url + " HTTP/1.0\\r\\n";	//设置请求
    			
    			try {
    				getConnect();	//连接服务器
    			} catch (IOException e1) {
    				
    				e1.printStackTrace();
    			}
    		}
    	}
    	
    	public void getConnect() throws IOException{
    		
    		Socket socket = new Socket("localhost", 8080);	//new socket对象访问服务器
    		socket.setSoTimeout(10000);						//设置访问超时的时限,此处设置为10秒
    		
    		//获取一个输入流和一个输出流,并将两个流都包装起来
    		OutputStream outputStream = socket.getOutputStream();
    		PrintWriter socketOutput = new PrintWriter(new OutputStreamWriter(outputStream));
    		InputStream inputStream = socket.getInputStream();
    		BufferedReader socketInput = new BufferedReader(new InputStreamReader(inputStream));
    		
    		//将处理后的用户请求写入输出流,此时的请求格式为http的请求行的格式
    		socketOutput.println(request);//将用户请求放入输出流中,传送给服务器
    		socketOutput.flush();
    		//----以上是处理发送请求到服务器的操作
    		
    		//----以下是处理服务器反馈的结果
    		String responseline = new String();	//保存每次从流中取出的信息
    		String response = new String();		//保存服务器返回的所有信息
    		
    		responseline = socketInput.readLine();	//从流中读取一行内容
            while(responseline != null){
                System.out.println(responseline);
                response = response.concat(responseline);
                responseline = socketInput.readLine();
            }
            
            jEditorPane.setText(response);	//将服务器返回的内容写入浏览器中
            jEditorPane.repaint();			//重画一下浏览器的显示部分
    	}
    }
    

    客户端运行起来的样子会在最后演示。

    --------------------------------------------------------------------------------------小分割线

    服务器端写了五个类,分别是:
    Server.java(主类)
    MyServer.java(多线程服务器实现类)
    Request.java(包装请求类)
    Response.java(包装回复类)
    ServletCon.java(ServletCon是servlet容器的意思。)

    具体代码如下:

    Server.java(主类):
    package com.server;
    
    import java.io.IOException;
    
    public class Server {
    
    	public static void main(String[] args) throws IOException{
    		
    		MyServer myserver = new MyServer(); //生成服务器对象
    	}
    }
    

    MyServer.java(多线程服务器实现类):
    package com.server;
    
    import java.io.BufferedReader;
    import java.io.Closeable;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.URL;
    
    import javax.servlet.ServletException;
    
    //此类实现Runnable接口,以实现多线程功能
    public class MyServer implements  Runnable  {
    	
    	int port = 8080;					//定义监听端口
    	ServerSocket serverSocket = null;	//定义一个服务Socket
    	Socket socket  = null;				//定义一个普通Socket
    	String requestline = null;			//定义一个字符串保存用户的请求行
    	
    	public MyServer() throws IOException{
    	
    		serverSocket = new ServerSocket(8080);		//监听端口8080,参数为端口号
    		System.out.println("Server服务已经启动。。。。");
    		
    		//while死循环监听请求,用线程去处理请求
    		while(true){
    			socket = serverSocket.accept();
    			Thread thread = new Thread(this);	//将当前对象作为线程参数
    			thread.start();						//启动线程,执行run()方法
    		}
    	}
    	
    	//重写run()方法
    	public void run(){
    		
    		//定义一个输出流和一个输入流
    		InputStream inputStream = null;
    		OutputStream outputStream = null;
    		
    		try {
    			inputStream = socket.getInputStream();		//获取输入流
    			outputStream = socket.getOutputStream();	//获取输出流
    			
    			//通过Request的构造方法,将输入流传入,然后通过getUri就可以获取用户的请求,并会返回处理后的请求
    			Request clientrequset = new Request(inputStream);	//生成Request对象,将此流传入
    			requestline = clientrequset.getUri();		//调用getUri方法获取请求行中的路径
    			
    			//判断是请求页面还是请求servlet
    			if(requestline.startsWith("servlets/")){
    				
    				//如果是servlets请求,先将输入流传给Response对象
    				Response responseservlet = new Response(outputStream);
    				//此处生成servlet容器对象,用来处理servlet程序,需要将请求的内容传给servlet容器
    				ServletCon servletCon = new ServletCon(requestline);
    				
    				try {
    					//通过processServletRequest()方法处理用户请求,需要一个Request对象,和一个Response对象
    					servletCon.processServletRequest(clientrequset, responseservlet);
    				} catch (ServletException e) {
    					
    					e.printStackTrace();
    				}
    				System.out.println("处理servlet");
    			}
    			else{
    				
    				//如果是请求页面的话,将请求的内容通过setRequest()方法传给Response对象
    				Response responsehtml = new Response(outputStream);//生成一个Response对象,并将输出流传入
    				responsehtml.setRequest(requestline);	//将请求对象传入
    				responsehtml.sendStaticResource();		//通过sendStaticResourct()方法将请求的页面返回给客户端
    				System.out.println("处理html");
    			}
    			
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }

    Request.java(包装请求类),因为此类实现了ServletRequest接口,实现的一些方法没有用,
    所以只给出需要用到的方法和扩展的方法:
    package com.server;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.UnsupportedEncodingException;
    import java.security.Principal;
    import java.util.Enumeration;
    import java.util.Locale;
    import java.util.Map;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletInputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    
    public class Request implements ServletRequest{
    
    	InputStream inputStream = null;		//定义一个输入流,用来接收socket输入流的引用
    	public static String clientrequest = new String();	//保存用户请求行
    	
    	public  Request(InputStream input) {
    		this.inputStream = input;	//获取输入流
    	}
    	
    	//获取用户请求行中的uri标识
    	public String getUri(){
    		
    		String requestString = new String();	//保存uri
    		
    		try{
    			BufferedReader socketInput = new BufferedReader(new InputStreamReader(inputStream));
    			
    			requestString = socketInput.readLine();//读取用户请求行,保存在requestString中
    			clientrequest = requestString;	//此处需要赋值一次,因为在Servlet程序中要用到
    			requestString = this.parseUri(requestString);	//调用parseUri处理用户请求行
    			
    		}catch(Exception e){
    			e.printStackTrace();
    		}
    
    		return requestString;	//将uri返回,用作比较
    	}
    	
    	//处理用户请求行
    	private String parseUri(String requestString){
    		
    		int beginindex = requestString.indexOf(" ");
    		int endindex = requestString.lastIndexOf(" ");
    		//因为请求行中的资源标识符在两个空格之间,所以取到两个空格的索引
    		
    		//取出资源定位符
    		requestString = requestString.substring(beginindex+2, endindex);
    		
    		return requestString;	//将定位符返回
    	}
    	
    	...
    	
    }

    Response.java(包装回复类),此类同上,实现了ServletResponse接口,有些没用到的方法
    就没有贴出来:
    package com.server;
    
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.util.Locale;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Response implements ServletResponse{
    
    	String requestline;			//定义请求行字符串,用来保存用户请求
    	OutputStream output = null;	//定义一个输出流
    	
    	//通过构造方法 ,获取到输出流
    	public Response(OutputStream output){
    		
    		this.output = output;
    	}
    	
    	//处理客户的静态页面请求
    	public void sendStaticResource() throws IOException{
    		
    		File responsehtml = new File(requestline);	//生成用户请求页面对象
    		
    		//判断文件是否存在
    		if(responsehtml.exists()){
    			//存在的话,读取文件中的内容,并放到输出流中
    			FileReader fileReader = new FileReader(responsehtml);
    			PrintWriter socketOutput = this.getWriter();
    			
    			//读取文件内容,并写入输出流
    			int i;
    			while((i = fileReader.read()) != -1){
    				socketOutput.print((char)i);	//转换成char型	
    			}
    			
    			socketOutput.close();	//关闭输出流
    		}else{
    			//如果不存在,则输出404
    			PrintWriter socketOutput = this.getWriter();
    			socketOutput.println("404 NotFound");
    			socketOutput.close();	//关闭输出流
    		}
    	}
    	
    	//获取请求行
    	public void setRequest(String requestline){
    		
    		this.requestline = requestline;//获取到Request对象
    	}
    	
    	//重写此方法
    	public PrintWriter getWriter() throws IOException {
    	
    		return new PrintWriter(new OutputStreamWriter(output));
    	}
    	
    	...
    }

    ServletCon.java(ServletCon是servlet容器的意思。):
    package com.server;
    
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    import javax.servlet.Servlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class ServletCon {
    
    	ServletRequest request;
    	ServletResponse response;
    	String requestline;
    	
    	//通过构造方法获取到用户请求的内容
    	public ServletCon(String requestline) {
    		
    		this.requestline = requestline;
    	}
    	
    	//处理servlet请求
    	public void processServletRequest(Request request, Response response) throws ServletException, IOException{
    		
    		this.request = request;		//获取到Request对象
    		this.response = response;	//获取到Response对象
    		
    		String servletname = getServletName(requestline);	//通过getServletName()方法获取到用户请求的类名
    		
    		Servlet servlet = loadServlet(servletname);			//通过类名获取到对象的servlet程序
    		servlet.service(request, response);					//执行servlet的service方法
    	}
    	
    	//通过servletname导入servlet程序
    	private Servlet loadServlet(String servletname) throws ServletException, IOException {
    		
    		//此处的URL要定义到包名之外,不能连报名定义在一块
    		URLClassLoader loader = new URLClassLoader(new URL[] { new URL("file:E:\\Eclipesworkspace\\fenbushi3\\bin") });  
            Servlet servlet = null;
            
            try {  	
            	//此处注意在获取类文件的时候需要写全路径,也就是包含包名
                Class servletClass = loader.loadClass("com.servlets."+servletname);  
                servlet = (Servlet) servletClass.newInstance();	//实例化一个对象
    
            } catch (ClassNotFoundException e) {  
                e.printStackTrace();  
            } catch (InstantiationException e) {  
                e.printStackTrace();  
            } catch (IllegalAccessException e) {  
                e.printStackTrace();  
            }  
            return servlet;  
    		
    	}
    
    	//通过用户的请求行获取到请求的内容
    	public String getServletName(String requestline){
    		
    		int beginindex = requestline.indexOf("/");
    		int endindex = requestline.length();
    		
    		String servletname = requestline.substring(beginindex+1, endindex);
    		
    		return servletname;
    	}
    	
    }

    ------------------------------------------------------------------------------------------------------小分割线

    以上内容就是服务器端和客户端的代码,接下来还有一个用户请求的html页面的代码
    和一个servlet程序代码。

    html页面代码:
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    	<center>
    		<h1>this is a html page</h1>
    	</center>
    </body>
    </html>

    servlet程序代码:
    package com.servlets;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.GenericServlet;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.server.Request;
    import com.server.Response;
    
    public class MyServlet extends HttpServlet{
    
    	//重写service方法
    	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    		
    		Request request = (Request)req;		//强制转化成子类对象
    
    		String clientrequest = request.clientrequest;	//获取到完整请求行
    		
    		//以下是获取到用户请求方式GET或者是POST
    		int beginindex = 0;
    		int endindex = clientrequest.indexOf(" ");
    		String requestmethod = clientrequest.substring(beginindex, endindex);
    		//System.out.println(requestmethod);
    		
    		//根据不同的请求方式调用不用的方法,默认是POST
    		if(requestmethod.equals("POST")){
    			doPost(req, res);
    		}else if(requestmethod.equals("GET")){
    			doGet(req, res);
    		}
    
    	}
    
    	//重写doPost方法
    	protected void doPost(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    
    		PrintWriter socketOutput = res.getWriter();	//获取到输出流
    		
    		//输出一句HelloWorld到客户端
    		socketOutput.println("<h1>");
    		socketOutput.println("HelloWorld, I am servlet");
    		socketOutput.println("</h1>");
    		
    		socketOutput.flush();	//flush一下
    		socketOutput.close();	//关闭输出流
    	}
    
    	protected void doGet(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    		
    	}
    
    }


    ====================================================================分割线

    以上就是所有的代码,下面对运行的结果进行演示。

    代码结构如下图:


    启动服务器如下图:


    客户端请求html页面和请求不存在的html页面如下图:
    存在:

    不存在:


    请求servlet如下图:


    ====================================================================分割线

    总结:

    对于整个处理过程还没有完全吃透,还准备再看看,等差不多完全明白后,再来整理
    一篇博文。这里面涉及到的知识点还会再回来整理,时间不多了,马上断电了,得赶紧保
    存了。
    对了,还没有测试多线程和网络中访问的情况,现在只是在本地可以执行。

    展开全文
  • web服务器设计文档

    2013-05-30 00:22:43
    完成一个简单WEB服务器的设计与实现,要求能够通过HTTP GET命令获得一个简单的HTML文件,这是web服务器开发总文档,由概要设计到实验结果,需要课程设计的可以下了。。
  • 摘要:随着互连网发展,嵌入式系统Internet结合越来越紧密,如何通过网络共享嵌入式应用系统信息已经成为业界研究热门课题,嵌入式Web服务器便应运而生。嵌入式Web服务器是嵌入式技术网络化一项重要应用,它...
  • 在这套入侵防御系统中,可以通过制定策略来检测所有访问Web服务器的行为,可以有效地阻止恶意攻击从而保护Web服务器的安全。这套入侵防御系统的策略引擎可以加载和调用Lua语言编写的策略脚本,使策略脚本的编写更加...
  • 针对现代航空机务维修过程中的管理问题,就提出了基于Web的航空机务维修信息系统的设计。根据B/S架构实现航空机务维修信息系统的设计,前端部分使用CSS实现,创建以Boottrap为基础的前端框架。后端使用Python进行...
  • 随着网络通信技术和嵌入式技术的发展,基于嵌入式W.eb服务器的视频监控系 统已成为监控领域的发展趋势,采用B/S架构的嵌入式W曲服务器,监控者无需到 现场操作,系统成本低廉,设备体积小巧,安装方便,故障维护...
  • 某企业有办公室、财务部、销售部、设计部、生产部5个部门,每个部门配置8台计算机。你作为网络管理员,需要...(3) 内、外网用户均需要访问企业内部一台Web服务器,可以在路由器中使用Static NAT技术来解决这一问题。
  • 设计中来,在防火墙系统自身的设计中,实现基于Web管理的思想;最后,在Linux 操作系统中,通过Apache服务器,使用perl编写公共网关接口脚本,实现了一个基本 的基于Web管理的包过滤防火墙,论证了基于Web管理所带来...
  • 这种设计与写法适用于角色权限。 (若要适用个人权限则通过用户ID建立权限表就OK) 表设计 用户表:用户ID,账号,密码,用户类型ID 模块表:模块ID,模块Url,模块Code 权限表:权限ID,用户类型ID,模块ID,...
  • 基于J2EE和Ajax的Web应用程序的设计与实现 黎军军(北京交通大学计算机与信息技术学院,北京100044) 摘要: 对传统Web应用与Ajax模式的Web应用进行了比较,详细分析了Ajax与J2EE的集成设计模式,并通过具体简单的...
  • 在上次的FreeBSD和linux的nginx静态文件性能对比测试 后,我萌发了自己动手做一个简单Web Server来...本文主要介绍这个HTTP服务器的原理和设计过程。 阅读了一些文章(见最后的参考阅读)后,我整理出了以下要点:...
  • 1、掌握在ARM开发板实现一个简单WEB服务器的过程 2、学习在ARM开发板上的SOCKET网络编程 3、学习在Linux下的signal()函数的使用 实验内容 学习使用socket进行通讯编程的过程,了解一个实际的网络通讯应用程序整体...
  • 介绍了基于We b模式网上工资查询系统体系结构和基本功能实现;分析了该系统开发工具和关键技术,从稳定性、保密性等多个角度阐述了系统优越之处。该系统采用浏览器/服务器(B/ S)浏览器访问方式,操作简单;在...
  • 根据服务器web 管理中 文件,注册表,网络防护功能设计一个简单的类http协议 利用这个协议,来完成控制伪agent功能,如 让 伪agent 防护某个文件夹,防护注册表某个位置,阻塞某个ip, 伪agent 要将控制命令...
  • 本文主要讲述利用 Java Web 相关技术来制作一个简单论坛。 通过实际制作,实现了 BBS 论坛系统应有一些基本功能,如:登陆 功能,通过在登陆界面输入用户名和密码来实现会员登录,用户只 有登录成功了才能进行...
  • 掌握在ARM开发板实现一个简单WEB服务器的过程。 学习在ARM开发板上的SOCKET网络编程。 学习在Linux环境下signal()函数的调用。 实验原理 在Linux PC上,利用arm-linux-gcc编译器,可编译出针对Li...
  • Linux系统下WEB服务器的架设性能优化一:概述 Linux系统的特点发展简单地说, Linux是一套免费使用和自由传播的类 Unix操作系统,它主要用于基于 Intel x86系列 CPU的计算机上。这个系统是由世界各地的成千上万...
  • JSP是近年来新出现一种动态交互式Web主页设计技术,它是一个服务器端脚本执行环境,它通过对.JSP文件进行解释执行,能构建一个动态、交互、高效的Web服务器应用环境。同以往动态网页实现手段复杂开发技术...
  • 随着信息技术的广泛使用,各类计算机考试也应运而生,这类考试多为上机考试,因此,考试的环境,即考试系统的设计实现非常重要。在网络技术逐渐渗入社会生活各个层面的今天,采用网络考试是一个很重要的方向。目前...
  • 简单 web 服务客户端开发实战个人报告 任务目标 选择合适 API,实现从接口或资源(领域)建模,到 API 设计的过程 使用 API 工具,编制 API 描述文件,编译生成服务器、客户端原型 使用 Github 建立一个组织,...
  • 针对现有网络设备管理系统不足,设计实现了一种多节点网络设备管理系统。此系统由采集节点和主控节点组成,采集节点通过简单网络管理协议负责采集网络设备各种信息,然后通过传输控制协议将采集数据发送到...
  • 简单 web 服务客户端开发实战 概述 利用 web 客户端调用远端服务是服务开发本实验重要内容。其中,要点建立 API First 开发理念,实现前后端分离,使得团队协作变得更有效率。 任务目标 选择合适 API,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,101
精华内容 440
关键字:

简单web服务器的设计与实现