zoukankan      html  css  js  c++  java
  • 手写一个简单的Http服务器

    什么是Http协议?

    Http协议: 对浏览器客户端 和 服务器端 之间数据传输的格式规范

    Http是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。
    HTTP协议的主要特点可概括如下:
    1.支持客户/服务器模式。
    2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
    3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
    4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
    5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

    Http是使用Socket中的TCP协议实现,基于请求(客户端)、响应(服务器端)

    实例:http://127.0.0.1:8080/项目路径

    Http协议分为请求报文和响应报文

    请求模式 Get、Post、Delete

    默认Http请求参数(请求报文)

    GET / HTTP/1.1

    Host: 127.0.0.1:8080

    Connection: keep-alive

    Cache-Control: max-age=0

    Upgrade-Insecure-Requests: 1

    User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2783.4 Safari/537.36

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

    Accept-Encoding: gzip, deflate, sdch

    Accept-Language: zh-CN,zh;q=0.8

    Cookie: Hm_lvt_b43c1c82b09cda6b125e6981fbde442c=1487946887,1487950668,1488114252; CNZZDATA1259976290=1895288300-1478441025-%7C1488116464

     

    Http响应报文

    HTTP响应报文与HTTP请求报文是对应的,也是分为三个部分。

      1、响应行

      2、响应头

      3、响应体

    项目结构图:

    上代码

    封装响应的数据类
    package cn.liuzhiw.server;
    
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.util.Date;
    
    /**
     * 封装响应的数据类
     * Created by 刘志威 on 2018/4/24.
     */
    public class Response {
        //空格
        private final String BLANK="  ";
        //换行
        private final String BR="
    ";
        //显示Http响应头
        private StringBuffer responseData;
        //封装网页信息
        private StringBuffer responseInfo;
        //字符缓冲输出流
        private BufferedWriter bufferedWriter;
        //响应的长度
        private long len;
        //初始化配置
        public Response(OutputStream outputStream){
            responseData=new StringBuffer();
            responseInfo=new StringBuffer();
            bufferedWriter=new BufferedWriter(new OutputStreamWriter(outputStream));
        }
        //创建头部信息
        private void createHeadInfo(int code){
            responseData.append("HTTP/1.1");
            responseData.append(BLANK);
            responseData.append(code + "").append(BLANK);
            switch (code){
                case 200:
                    responseData.append("ok");
                    break;
                case 404:
                    responseData.append("not found");
                    break;
                case 500:
                    responseData.append("server error");
                    break;
                default:
                    break;
            }
            responseData.append("Date:").append(new Date()).append(BR);
            responseData.append("Content-Type: text/html;charset=UTF-8").append(BR);
            responseData.append("Content-Length:").append(len).append(BR);
            responseData.append(BR);
        }
    
        /**
         * 填充页面类容
         * @param str
         * @return
         */
        public Response print(String str) {
            responseInfo.append(str);
            len += str.getBytes().length;
            return this;
        }
        /**
         * 发送数据
         * @throws IOException
         */
        public void connect(int code) throws IOException {
            createHeadInfo(code);
            bufferedWriter.append(responseData.toString());
            bufferedWriter.append(responseInfo.toString());
            //刷新
            bufferedWriter.flush();
            //关闭
            bufferedWriter.close();
        }
    }
    

      

    服务器核心配置类
    package cn.liuzhiw.server;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
    
    /**
     * 服务器核心配置类
     * Created by 刘志威 on 2018/4/24.
     */
    public class Server4 {
        //socket服务端
        private ServerSocket serverSocket;
        //端口号
        private final int PORT=8080;
        /**
         * 启动服务器
         */
        public void start() throws IOException {
            System.out.println("服务器启动成功.........");
            //监听服务器
            serverSocket=new ServerSocket(PORT);
            //接受客户端数据
            acceptClient();
            //关闭链接
            closeServer();
    
        }
    
        /**
         * 接受客户端数据
         * @throws IOException
         */
        public void acceptClient() throws IOException {
            //拿到socket客户端对象
            Socket accept = serverSocket.accept();
            //拿到输入流
            InputStream inputStream = accept.getInputStream();
            byte []data=new byte[20480];
            int read = inputStream.read(data);
            String message = new String(data, 0, read);
            System.out.println("客户端发送来的数据:"+message);
            //响应回去数据
            Response response=new Response(accept.getOutputStream());
            response.print("<html><head><title>响应页面</title></head><body>响应页面成功</body></html>");
            response.connect(200);
        }
        /**
         * 关闭链接
         * @throws IOException
         */
        public void closeServer() throws IOException {
            if (serverSocket!=null){
                serverSocket.close();
            }
        }
    }
    

      

    服务器启动入口
    package cn.liuzhiw.app;
    
    import cn.liuzhiw.server.Server4;
    
    import java.io.IOException;
    
    /**
     * 服务器启动入口
     * Created by 刘志威 on 2018/4/24.
     */
    public class App {
        public static void main(String[] args) throws IOException {
            Server4 server=new Server4();
            server.start();
        }
    }
    

      html请求的页面

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Http服务器post方式提交参数</title>
    </head>
    <body>
        <pre>
         method:请求方式 get/post
         get:数据量小,安全性不高  默认方式
         post:量大,安全性相对高
         action:请求的服务器路径
         id:编号:前端区分唯一,js使用
         name:名称后端(服务器)区分唯一性,获取值
               只要提交数据给后台,必须存在name;
        
        </pre>
       <form action="http://127.0.0.1:8080/index" method="post">
        用户名称:<input type="text" name="uname" id="uname">
        用户面:<input type="password" name="pwd" id="pwd">
       <input type="submit">
       </form>
    </body>
    </html>

    页面效果和后台效果

  • 相关阅读:
    C#24种设计模式汇总
    传智播客C++视频学习笔记(5)
    传智播客C++视频学习笔记(3)
    传智播客C++视频学习笔记(1)
    Learning hard 网络编程
    Learning hard 学习笔记
    男人和女人 访问者模式
    其实你不懂老板的心 解释器模式
    项目多也别傻做 享元模式
    git常用命令
  • 原文地址:https://www.cnblogs.com/liuzhiw/p/8934430.html
Copyright © 2011-2022 走看看