zoukankan      html  css  js  c++  java
  • java实现简单web服务器(分析+源代码)

    在日常的开发中,我们用过很多开源的web服务器,例如tomcat、apache等等。现在我们自己实现一个简单的web服务器,基本的功能就是用户点击要访问的资源,服务器将资源发送到客户端的浏览器。为了简化操作,这里不考虑资源不存在等异常情况。web服务基于的是HTTP协议,用户在浏览器的地址栏输入要访问的地址,服务器如何得到该地址是个关键。先看下一般的HTTP请求和响应报文的一般格式:

    HTTP 请求报文

    HTTP 响应报文


    web服务器获取一个用户的连接时,会初始化一个线程和用户通信,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.Socket;
     
     
    //每有一个连接建立时,服务器分出一个通信的线程
    public class CommunicateThread extends Thread{
        //与客户端通信的套接字
        Socket client;
         
        public CommunicateThread(Socket s) {
            client = s;
        }
         
        //获取浏览器请求资源的路径
        public String getResourcePath(String s){
            // 一般的HTTP请求报文的第一行是“GET /index.html HTTP/1.1”
            // 我们要获取的就是中间的"/indext.apsx"
             
            //获取资源的位置
            String s1 = s.substring(s.indexOf(' ')+1);
            s1 = s1.substring(1,s1.indexOf(' '));
             
            //默认资源为index.html
            if(s1.equals(""))
                s1 = "index.html";
             
            return s1;
        }
     
        public void sendFile(PrintStream out,File file){
            try{
                DataInputStream in  = new DataInputStream(new FileInputStream(file));
                int len = (int)file.length();
                byte buf[] = new byte[len];
                in.readFully(buf);//读取文内容到buf数组中
                out.write(buf,0,len);
                out.flush();
                in.close();
            }
            catch(Exception e){
                System.out.println(e.getMessage());
                System.exit(1);
                }
        }
         
        public void run(){
            try{
                //获取用户的IP地址和端口号
                String clientIP = client.getInetAddress().toString();
                int clientPort = client.getPort();
                //创建输出流对象
                PrintStream out = new PrintStream(client.getOutputStream());
                //创建输入流对象
                DataInputStream in = new DataInputStream(client.getInputStream());
                //读取浏览器提交的请求
                String msg = in.readLine();
                 
                 
                //获取文件路径
                String fileName = getResourcePath(msg);
                System.out.println("The user asked for resource: "+fileName);
                File file = new File(fileName);
                 
                if(file.exists()){
                    //根据响应报文格式设置
                    System.out.println(fileName+" start send");
                     
                    out.println("HTTP/1.0 200 OK");
                    out.println("MIME_version:1.0");
                    out.println("Content_Type:text/html");
                    int len = (int) file.length();
                    out.println("Content_Length:"+len);
                    out.println("");//报文头和信息之间要空一行
                     
                    //发送文件
                    sendFile(out,file);
                     
                    out.flush();
                }  
                client.close();    
            }
            catch(Exception e){
                System.out.println(e.getMessage());
            }      
        }
         
     
     
    }

    服务器主要负责初始化套接字和线程,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    import java.net.ServerSocket;
    import java.net.Socket;
     
     
    public class WebServer {
     
     
        public static void main(String[] args) {
            int Port = 12345;//端口号,由于这里是测试,所以不要使用常用端口
            //创建两个套接字
            ServerSocket server = null;
            Socket client = null;
            try{
                server = new ServerSocket(Port);
                //服务器开始监听
                System.out.println("The WebServer is listening on port "+server.getLocalPort());
                while(true){
                    client = server.accept();
                    //多线程运行
                    new CommunicateThread(client).start();
                }
            }catch(Exception e){
                System.out.println(e.getMessage());
            }
        }
     
    }


    运行测试:

    编写一个index.html文件

    1
    <h1>This is the index of my WebServer</h1><hr>
    放到项目文件的根目录,然后在浏览器地址栏输入:“localhost:12345/index.html”,就可以看到位于服务器端的html文件了。注意由于服务器是死循环,重启服务器会发现指定的端口已被绑定,只需要进入任务管理器,关闭"Java(TM) Platfrom SE binary"进程即可。最后结果如下所示:


    这个服务器程序很简陋,还有很大的改进余地。大家可以自己尝试改进。这里可以尝试一下访问其他的文件,发现时成功的,说明这服务器很不安全呀。



  • 相关阅读:
    图解插入排序--直接插入排序
    在项目中代替DevExpress(一)
    java web servlet
    一元夺宝项目设计(上)
    一元夺宝项目设计(中)
    一元夺宝项目设计(下)
    ORM之四:调用入口与调用示例
    ORM之三:DbProvider与DbFactory
    ORM之二:核心接口与扩展操作
    ORM之一:适合我的ORM
  • 原文地址:https://www.cnblogs.com/timssd/p/5028967.html
Copyright © 2011-2022 走看看