精华内容
下载资源
问答
  • 基于netty构建http服务器

    万次阅读 2020-11-24 16:31:21
    基于netty构建http服务器 基于Netty构建Http服务的流程如下: Client向Server发送http请求。 Server端对http请求进行解析。 Server端向Client发送http响应。 Client对http响应进行解析。 流程图如下: 服务器端...

    基于netty构建http服务器

    基于Netty构建Http服务的流程如下:

    1. Client向Server发送http请求。
    2. Server端对http请求进行解析。
    3. Server端向Client发送http响应。
    4. Client对http响应进行解析。

    流程图如下:

    在这里插入图片描述

    服务器端实现

    package com.morris.netty.protocol.http;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.http.*;
    import io.netty.util.CharsetUtil;
    import lombok.extern.slf4j.Slf4j;
    
    import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
    import static io.netty.handler.codec.http.HttpResponseStatus.OK;
    import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
    
    @Slf4j
    public class Server {
    
        private static final int port = 8899;
    
        public static void main(String[] args) throws Exception {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel ch) throws Exception {
                                ch.pipeline().addLast(new HttpRequestDecoder()); // 请求消息解码器
                                ch.pipeline().addLast(new HttpObjectAggregator(65536));// 目的是将多个消息转换为单一的request或者response对象
                                ch.pipeline().addLast(new HttpResponseEncoder());//响应编码器
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        FullHttpRequest request = (FullHttpRequest) msg;
                                        log.info("method:{}", request.method().name());
                                        log.info("uri:{}", request.uri());
                                        log.info("content:{}", request.content().toString(CharsetUtil.UTF_8));
    
                                        FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
                                        response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
                                        ByteBuf buffer = Unpooled.copiedBuffer("<h3>hello world</h3>", CharsetUtil.UTF_8);
                                        response.content().writeBytes(buffer);
                                        buffer.release();
                                        request.release();
                                        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
                                    }
                                });// 业务逻辑
                            }
                        });
                ChannelFuture future = b.bind("127.0.0.1", port).sync();
                log.info("HTTP服务器启动,网址是 : " + "http://127.0.0.1:" + port);
                future.channel().closeFuture().sync();
            } finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
    

    在浏览器输入http://127.0.0.1:8899就可以看到页面显示hello world

    客户端实现

    package com.morris.netty.protocol.http;
    
    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.http.*;
    import io.netty.util.CharsetUtil;
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class Client {
    
        public static void main(String[] args) throws InterruptedException {
    
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(workerGroup)
                        .channel(NioSocketChannel.class)
                        .handler(new ChannelInitializer() {
    
                            @Override
                            protected void initChannel(Channel ch) throws Exception {
                                ch.pipeline().addLast(new HttpResponseDecoder()); // 响应解码器
                                ch.pipeline().addLast(new HttpObjectAggregator(65536));
                                ch.pipeline().addLast(new HttpRequestEncoder()); // 请求编码器
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
    
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        FullHttpResponse httpResponse = (FullHttpResponse)msg;
                                        log.info("status:{}", httpResponse.status());
                                        log.info("headers:{}", httpResponse.headers());
                                        log.info("body:{}", httpResponse.content().toString(CharsetUtil.UTF_8));
                                        httpResponse.release();
                                    }
    
                                    @Override
                                    public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                        DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/");
    
                                        // 构建http请求
                                        request.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
                                        request.headers().set(HttpHeaderNames.CONTENT_LENGTH, request.content().readableBytes());
                                        // 发送http请求
                                        ctx.writeAndFlush(request);
                                    }
                                });
                            }
                        });
    
                // 启动 server.
                ChannelFuture f = b.connect("127.0.0.1", 8899).sync();
    
                // 等待socket关闭
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
            }
        }
    }
    
    展开全文
  • 什么是http服务器

    万次阅读 多人点赞 2019-02-25 10:13:43
    本篇文章旨在从服务器后台开发的角度剖析一个简单的http服务器的运行原理. 我们知道浏览器是http(s)的客户端,目的是连接远程的http服务器,然后服务器返回浏览器数据.浏览器接收数据解析数据之后展现出来.我们看到的...

    本篇文章旨在从服务器后台开发的角度剖析一个简单的http服务器的运行原理.

    我们知道浏览器是http(s)的客户端,目的是连接远程的http服务器,然后服务器返回浏览器数据.浏览器接收数据解析数据之后展现出来.我们看到的外在表现就是,浏览器访问一个url,然后就得到相应的web页面.

    同样我们知道,浏览器与http服务器是通过http协议,传输层是tcp协议,因为他是有连接,可靠的协议.关于http协议简单的介绍一下:


    一个标准的HTTP请求由以下几个部分组成

    <request-line>
    <headers>
    <CRLF>
    [<request-body><CRLF>]

    在HTTP请求中,第一行是请求行(request-line),用来说明请求类型、要访问的资源(URL)以及使用的HTTP版本;
    紧接着是多行头部(headers)信息,用来说明服务器要使用的附加信息;
    头部信息之后是一个回车换行符(\r\n),用于标明头部信息的结束。
    以上是必须内容,根据需要可在头部信息结束之后增加主体数据(request-body);

    主体数据之后是一个回车换行符(\r\n),用于标明主体数据的结束。

    例如,我们可以在IE浏览器上输入下面的网址:

    http://localhost:8000/hello/index.html

    HTTP请求的头部信息如下:

    GET /hello/index.html HTTP/1.1
    Accept: */*
    Accept-Language: zh-cn
    Accept-Encoding: gzip, deflate
    Host: localhost:8000
    Connection: Keep-Alive
    Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

    收到请求数据之后,服务器解析,毕竟是明文字符,这个简单.然后服务器就知道了客户端的要求--获取目录hello/index.html文件.服务器读取文件内容发送给浏览器就好了.

    后来随着业务逻辑越来越复杂,单单获取某个html文件功能早已不能满足需求,个性化需求呼之欲出.比如在线问卷调查表,他究竟是怎么把我们填写的数据传递给服务器的呢?

    你可能会说那不是一样,客户端发送什么内容,服务器就接收什么内容.可是你想过没有,每个网站的需求是不一样的,本来服务器接收到浏览器的请求数据已经是够复杂的了,还让服务器来解析数据并响应不同的数据处理,这不太现实.

    一般的,服务器最好只接收数据,如果让服务器也处理数据逻辑,势必会让服务器变得很复杂,稳定性也得不到保证.

    另外一个角度是为了让程序复用,提高生产效率.也就是说,如果不关注业务逻辑,只注重接收数据,那么服务器程序可以给任何一个开发者使用.换句话说,我们不用从头开始写.直接使用现有的高性能的服务器就可以满足需求了.例如公司白领中午要吃饭,不可能跑回家自己去做饭吃,自己叫外卖就好了.

    但是现实问题仍然没有解决,通过什么方式去处理业务逻辑呢?

    你要给手机充电时,把插头插入插线板就能获取电了.插线板有接口,提供了电.

    同理服务器程序最好也提供接口,浏览器通过统一的接口给服务器,然后我们从服务器接口中获取我们想要的数据.获取数据之后我们可以把数据交给第三方程序来处理逻辑,这样就做到与服务器业务分离了,good iead.

    事实上,现在的http服务器就是这么做的,不过很复杂而已.下一篇开始为您介绍这些接口.

    附录:HTTP Request Header 请求头

     

    Header 解释 示例
    Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
    Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
    Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
    Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
    Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
    Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
    Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
    Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
    Content-Length 请求的内容长度 Content-Length: 348
    Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
    Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
    Expect 请求的特定的服务器行为 Expect: 100-continue
    From 发出请求的用户的Email From: user@email.com
    Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
    If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
    If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
    If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
    Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
    Pragma 用来包含实现特定的指令 Pragma: no-cache
    Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Range 只请求实体的一部分,指定范围 Range: bytes=500-999
    Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives/71.html
    TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
    Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
    User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
    Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning


    --------------------- 
    作者:Shonm 
    来源:CSDN 
    原文:https://blog.csdn.net/zxm342698145/article/details/79995039 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • 搭建http服务器

    千次阅读 2019-06-04 15:58:37
    使用tomcat搭建HTTP文件下载服务器 用简单的方法实战演练搭建http服务器(Windows上) 超简单——自己搭建ftp服务器(python nodejs)
    展开全文
  • http服务器摘要一、什么是http服务器二、如何自己简单实现一个http服务器三、自己实现的http服务器四、Http服务器实现(Java) 摘要 web开发一直是行业热门技术,而要做web程序就离不开http服务器,现在主流的http...

    摘要

           web开发一直是行业热门技术,而要做web程序就离不开http服务器,现在主流的http服务器用的最广的如tomcat,apache。还有商用版本的各式各样的http服务器,而再行业类各种微服务,各种web开发技术层出不穷,都是基于这些服务器上的架构上的使用,并没有从本质上提高服务器运行的效率,笔者在研究http服务的过程中,就花了一早上来写了这样一个http服务器展示http服务器工作的流程。

    一、什么是http服务器

           HTTP服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以处理浏览器等Web客户端的请求并返回相应响应,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。1目前最主流的三个Web服务器有Tomcat、Apache、 Nginx 。

    http服务器用来干什么:

           如下图所示,网络通过一个如tomcat一样的http服务器来获取一台计算机上的资源。计算机上的资源可以是计算机能提供的任何服务(包括文件,存储,计算能力等等)。
    服务器与网络的关系

           下图是tomcat中一个http请求的传递过程你,该图在tomcat官网可以找到。
           一个请求到响应主要经过了tomcat的Engine->Host->Pipeline->执行servece方法响应http请求。

    在这里插入图片描述

    二、如何自己简单实现一个http服务器

           一个简单的实现思路如下,最简单的过程通俗的说就是,请求进来,请求处理器将响应的结果生产出来,再有服务器发出响应。思路上一定是很简单的,实现一个良好可靠的http服务器确实一件很难的事。有很多复制的问题需要解决,如下:

    1. 什么样的请求能进来或者说是有效的?(第一层请求拦截)
    2. 请求的解析和响应结果的生成?(需要精通http协议)
    3. io模型如何选择,怎样充分利用发挥服务器性能?(涉及多线程,复杂的io模型)
    4. 可插拔要怎么实现?如tomcat可以通过一个servlet让开发人员进行处理。
    5. …等等,实现一个http服务器绝对是一件很困难的事,所有网络应用层都是基于这个向上设计的。
      实现一个http服务器的简单思路

    三、自己实现的http服务器

           说干就干,今早花了一个小时写了一个简单的demo来展示,先看下做出来的效果是什么样的。

           先在我项目配置的文件夹下放两张图片
    在这里插入图片描述

           通过浏览器加文件名的方式来访问试试结果:
    在这里插入图片描述
    在这里插入图片描述
           两张图片现在就可以通过网络来浏览了,怎么样,很神奇对吧,接下来就看下代码是怎么实现的?

    四、Http服务器实现(Java)

           HttpServer类:具体的server实现,并且将解析方法也在该类下:

    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.util.Properties;
    
    /**
     * Copyright(c)lbhbinhao@163.com
     * @author liubinhao
     * @date 2021/1/1
     * ++++ ______                           ______             ______
     * +++/     /|                         /     /|           /     /|
     * +/_____/  |                       /_____/  |         /_____/  |
     * |     |   |                      |     |   |        |     |   |
     * |     |   |                      |     |   |________|     |   |
     * |     |   |                      |     |  /         |     |   |
     * |     |   |                      |     |/___________|     |   |
     * |     |   |___________________   |     |____________|     |   |
     * |     |  /                  / |  |     |   |        |     |   |
     * |     |/ _________________/  /   |     |  /         |     |  /
     * |_________________________|/b    |_____|/           |_____|/
     */
    
    public class HttpServer {
        public static final String RESOURCE_PATH = "D:/image";
        public static void main(String[] args) throws IOException {
            ServerSocket server = new ServerSocket(80);
            while (true){
                Socket client = server.accept();
                InputStream inputStream = client.getInputStream();
                String s = handleNewClientMessage(inputStream);
                Request request = Request.parse(s);
                System.out.println(request);
                //假设请求的都是文件
                String uri = request.getUri();
                File file = new File(RESOURCE_PATH + uri);
                FileInputStream fileInputStream = new FileInputStream(file);
                FileChannel channel = fileInputStream.getChannel();
                ByteBuffer buffer = ByteBuffer.allocate((int) file.length());
                channel.read(buffer);
                buffer.rewind();
                Response response = new Response();
                response.setTopRow("HTTP/1.1 200 OK");
                response.getHeaders().put("Content-Type",readProperties(getType(request.getUri())));
                response.getHeaders().put("Content-Length",String.valueOf(file.length()));
                response.getHeaders().put("Server","httpserver-lbh");
                response.setBody(buffer.array());
                response.setOutputStream(client.getOutputStream());
                response.setClient(client);
                System.out.println(response);
                System.out.println(client.isClosed());
                //响应客户端
                response.service();
                inputStream.close();
                client.close();
            }
        }
    
    
        private static String handleNewClientMessage(InputStream inputStream) throws IOException {
            byte[] bytes = new byte[1024];
            int read = inputStream.read(bytes);
            StringBuilder buffer = new StringBuilder();
            if (read != -1) {
                for (byte b:bytes) {
                    buffer.append((char)b);
                }
            }
            return buffer.toString();
        }
    
        /**
         * 我个人放mimetype文件类型的文件,需要单独修改
         */
        private static final String MIME_PROPERTIES_LOCATION =
                "D:\\individual\\springcloudDemo\\src\\main\\java\\contentype.properties";
    
        public static String readProperties(String key) {
            System.out.println(System.getProperty("user.dir"));
            Properties prop = new Properties();
            try {prop.load(new FileInputStream(MIME_PROPERTIES_LOCATION));
                return prop.get(key).toString();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        public static String getType(String uri) {
            System.out.println("uri:" + uri);
            String stringDot = ".";
            String dot = "\\.";
            String[] fileName;
            if (uri.contains(stringDot)) {
                fileName = uri.split(dot);
                return fileName[fileName.length - 1];
            }
            return null;
        }
    
    }
    

           Request类,请求进来的形式:

    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Copyright(c)lbhbinhao@163.com
     * @author liubinhao
     * @date 2021/1/1
     * ++++ ______                           ______             ______
     * +++/     /|                         /     /|           /     /|
     * +/_____/  |                       /_____/  |         /_____/  |
     * |     |   |                      |     |   |        |     |   |
     * |     |   |                      |     |   |________|     |   |
     * |     |   |                      |     |  /         |     |   |
     * |     |   |                      |     |/___________|     |   |
     * |     |   |___________________   |     |____________|     |   |
     * |     |  /                  / |  |     |   |        |     |   |
     * |     |/ _________________/  /   |     |  /         |     |  /
     * |_________________________|/b    |_____|/           |_____|/
     */
    
    public class Request {
    
        private String method;
    
        private String uri;
    
        private String version;
    
        private byte[] body;
    
        private Map<String, String> headers;
    
        public String getMethod() {
            return method;
        }
    
        public String getUri() {
            return uri;
        }
    
        public String getVersion() {
            return version;
        }
    
        public byte[] getBody() {
            return body;
        }
    
        public Map<String, String> getHeaders() {
            return headers;
        }
    
        public void setMethod(String method) {
            this.method = method;
        }
    
        public void setUri(String uri) {
            this.uri = uri;
        }
    
        public void setVersion(String version) {
            this.version = version;
        }
    
        public void setHeaders(Map<String, String> headers) {
            this.headers = headers;
        }
    
        public void setBody(byte[] body) {
            this.body = body;
        }
        @Override
        public String toString() {
            return "Request{" +
                    "method='" + method + '\'' +
                    ", uri='" + uri + '\'' +
                    ", version='" + version + '\'' +
                    ", body=" + Arrays.toString(body) +
                    ", headers=" + headers +
                    '}';
        }
    
    
        private static final String CONTENT_SEPARATE_SIGN = "\r\n\r\n";
    
        private static final String LINE_SEPARATE_SIGN = "\r\n";
    
        private static final String SPACE_SEPARATE_SIGN = "\\s+";
    
        private static final String KV_SEPARATE_SIGN = ":";
    
        //**********************************解析请求*************************************
        private static void parseTopReq(Request req, String[] topReq){
            req.setMethod (topReq[0]);
            req.setUri    (topReq[1]);
            req.setVersion(topReq[2]);
        }
    
        private static void parseHeaders(Request req, String[] headerStr){
            HashMap<String, String> headers = new HashMap<>(12);
            for (String s : headerStr) {
                String[] keyValue = s.split(KV_SEPARATE_SIGN);
                headers.put(keyValue[0], keyValue[1]);
            }
            req.setHeaders(headers);
        }
    
    
        public static Request parse(String reqStr) {
            Request req = new Request();
            String[] httpInfo = reqStr.split(CONTENT_SEPARATE_SIGN);
            if (httpInfo.length==0){
                return null;
            }
            if (httpInfo.length > 1){
                req.setBody(httpInfo[1].getBytes());
            }
            String[] content  = httpInfo[0].split(LINE_SEPARATE_SIGN);
            // http first row of a http request
            String[] firstRow = content[0].split(SPACE_SEPARATE_SIGN);
            // http / get demo_path.type
            parseTopReq(req, firstRow);
            parseHeaders(req, Arrays.copyOfRange(content,1,content.length));
            return req;
        }
    }
    

           Response类,具体响应的结果:

    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Copyright..@lbhbinhao@163.com
     * Author:liubinhao
     * Date:2020/12/28
     * ++++ ______                           ______             ______
     * +++/     /|                         /     /|           /     /|
     * +/_____/  |                       /_____/  |         /_____/  |
     * |     |   |                      |     |   |        |     |   |
     * |     |   |                      |     |   |________|     |   |
     * |     |   |                      |     |  /         |     |   |
     * |     |   |                      |     |/___________|     |   |
     * |     |   |___________________   |     |____________|     |   |
     * |     |  /                  / |  |     |   |        |     |   |
     * |     |/ _________________/  /   |     |  /         |     |  /
     * |_________________________|/b    |_____|/           |_____|/
     */
    
    public class Response{
    
        private String topRow;
    
        private Map<String, String> headers = new HashMap<>(12);
    
        private byte[] body;
    
        private int responseCode;
    
        private OutputStream outputStream;
    
        public String getTopRow() {
            return topRow;
        }
    
        public void setTopRow(String topRow) {
            this.topRow = topRow;
        }
    
        public Map<String, String> getHeaders() {
            return headers;
        }
    
        public void setHeaders(Map<String, String> headers) {
            this.headers = headers;
        }
    
        public byte[] getBody() {
            return body;
        }
    
        public void setBody(byte[] body) {
            this.body = body;
        }
    
        public OutputStream getOutputStream() {
            return outputStream;
        }
    
        public void setOutputStream(OutputStream outputStream) {
            this.outputStream = outputStream;
        }
    
        public int getResponseCode() {
            return responseCode;
        }
    
        public void setResponseCode(int responseCode) {
            this.responseCode = responseCode;
        }
    
        public static final byte[] LINE_SEPARATE_SIGN_BYTES    = "\r\n".getBytes();
        public static final byte[] KV_SEPARATE_SIGN_BYTES      = ":".getBytes();
    
        private Socket client;
    
        public Socket getClient() {
            return client;
        }
    
        public void setClient(Socket client) {
            this.client = client;
        }
    
        //    如果头数据里不包含Content-Length: x 类型为Transfer-Encoding:
    //    chunked 说明响应数据的长度不固定,结束符已"\r\n0\r\n"这5个字节为结束符
        public void service() throws IOException {
            outputStream.write(this.getTopRow().getBytes());
            outputStream.write(LINE_SEPARATE_SIGN_BYTES);
            for (Map.Entry<String, String> entry : this.getHeaders().entrySet()){
                outputStream.write(entry.getKey().getBytes());
                outputStream.write(KV_SEPARATE_SIGN_BYTES);
                outputStream.write(entry.getValue().getBytes());
                outputStream.write(LINE_SEPARATE_SIGN_BYTES);
            }
            outputStream.write(LINE_SEPARATE_SIGN_BYTES);
            outputStream.write(this.getBody());
            outputStream.flush();
        }
    
    
        @Override
        public String toString() {
            return "Response{" +
                    "topRow='" + topRow + '\'' +
                    ", headers=" + headers +
    //                ", body=" + Arrays.toString(body) +
                    ", responseCode=" + responseCode +
                    ", client=" + client +
                    '}';
        }
    }
    

           mimetype文件,用来判断请求的类型,由于文件太大,只复制一部分,格式都一样:
    contentype.properties

    #mdb=application/x-mdb
    mfp=application/x-shockwave-flash
    mht=message/rfc822
    mhtml=message/rfc822
    mi=application/x-mi
    mid=audio/mid
    midi=audio/mid
    mil=application/x-mil
    mml=text/xml
    mnd=audio/x-musicnet-download
    mns=audio/x-musicnet-stream
    mocha=application/x-javascript
    movie=video/x-sgi-movie
    mp1=audio/mp1
    mp2=audio/mp2
    mp2v=video/mpeg
    mp3=audio/mp3
    mp4=video/mp4
    mpa=video/x-mpg
    mpd=application/vnd
    #ms-project
    mpe=video/x-mpeg
    mpeg=video/mpg
    mpg=video/mpg
    mpga=audio/rn-mpeg
    mpp=application/vnd
    #ms-project
    mps=video/x-mpeg
    mpt=application/vnd
    

    五、总结

           实现一个http服务什么是核心呢,就在名字里,就是http协议,http协议本质上就是一个基于文本解析表示特定的语义规则,只要读懂了这些规则就能够理解一个http服务器。
           但是要开发一个http服务器这个是远远不够的,还需要高超的编程技艺,个人上述只是一个小demo,看上去好些很简单的样子。在个人github上有一个更加完整的实现,基于nio和多线程,效率更高,实现的更加完善,并且支持断点续传的方式,github地址:https://github.com/haobinliu/app-server/tree/server-x-test/server-x/src/com/lbh

    欢迎一键三连


    1. 百度百科. HTTP服务器 ↩︎

    展开全文
  • 小型HTTP服务器

    千次阅读 2017-04-10 13:38:47
    本文的重点是介绍HTTP服务器的框架结构,旨在了解HTTP服务器的工作流程,所以我们在下面我们会实现一个多线程的HTTP/1.0版本服务器,这个HTTP服务器主要支持GET和POST方法。在实现HTTP服务器之前,我们首先要了解...
  • 区分Web服务器、HTTP服务器、应用程序服务器

    万次阅读 多人点赞 2018-04-04 16:58:08
    进程听到和看到web服务器、HTTP服务器、应用程序服务器,但一直不知道它们有什么区别,迷惑了好久,今天查看的很多博客,终于算是梳理通了,下面我就来总结一下它们的区别,顺别了解一些服务器。 首先我们要知道web...
  • Web服务器、HTTP服务器及应用服务器有何区别?Apache、Nginx、IIS、Tomcat、JBoss、Weblogic、WebSphere 都各属于哪种服务器? Web服务器是指驻留在Internet上的计算机程序,它的基本功能是提供Web信息浏览服务。...
  • HTTP服务器搭建

    千次阅读 2018-06-19 11:36:56
    借助hfs这个软件很轻易的搭建http服务器,这样做升级的话很效率高。。很多客户端做升级。需要在后台写服务端软件。这种沟通过socket来玩的话。很费精力。。后面看到hfs这个软件。然后在客户端用libcurl这个库来做...
  • 创建HTTP服务器 在Node.js中,可以很方便地创建一个HTTP服务器,只需调用http模块中的create Server方法即可 var server=http.createServer([requestListener]) 在createServer方法中,可以使用一个可选参数,参数...
  • web/http服务器实现

    千次阅读 2020-02-08 14:18:45
    需求分析:实现基本的HTTP服务器,支持浏览器的访问(支持标准http协议) 接收浏览器发送HTTP请求; 解析请求数据,请求方式(GET),请求文件(html…),协议版本; 根据请求构建响应头,发送响应头: ...
  • Qt Http服务器简单变成https服务器

    千次阅读 2018-05-11 18:05:10
    一开始qt http服务器还是好简单,因为就是TCP连接上面一个简单协议。后来听说发布小程序必须用到https+域名,估计好多刚开始往小程序里跑的小伙子都哭晕在测所。不过我不负责写小程序,我负责搞用qt 写个http的...
  • Java 简单实现HTTP服务器

    万次阅读 2019-01-03 16:56:34
    HTTP服务器  解释: 个人理解,http服务器就是解析http请求信息,并解析信息;然后根据信息做后续事情。   Http请求格式与响应格式      核心代码   package com_2.Httpserver; import java.io....
  • HFS搭建HTTP服务器

    万次阅读 2018-06-12 17:39:34
    本文介绍用HTTP服务器工具软件HFS建立一个临时的HTTP文件服务,使能通过手机浏览器等访问下载计算机中的指定文件。 1. 简介 HFS ~Http File Server,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案...
  • Qt Http QHttpMultiPart上传文件到java http服务器 1.最近项目用到了Qt上传文件到HTTP服务器,由于之前做过一个http接收文件的服务器,所以直接拿来调试。由于对http的了解一个不够深入,调试了许久都没有成功上传...
  • 手写Http服务器

    千次阅读 2020-10-31 12:03:29
    你写的一个Html页面,丢到服务器,启动一个Web服务(Tomcat/Nginx),然后大家就可以访问了,为什么?...HTTP允许Web服务器和浏览器通过网络发送和接收数据,是一种基于【请求-响应】的协议。 说白了HT
  • c语言编写http服务器

    千次阅读 2018-09-27 10:26:24
    一直想弄一下http服务器,一直没有深入的去看http协议。 昨天研究了一天,查看源码和优化,终于实现了。也稍微的理解了一下http协议。 身为一个嵌入式工程师,需要了解http协议吗?显然是必要的, 例如:你有一个...
  • eNSP模拟HTTP服务器 HTTP服务器设置 Cliient5客户端信息配置
  • 在很多情况下,需要在本地开启http服务器来测试。所以就需要一个简单的省事好用的http服务器。以前的时候,都是使用php的本地环境,但是,自从学了nodejs,发现了http-server好东西。不用配置直接在当前文件夹内打开...
  • pomelo服务器集群中集成http服务器

    千次阅读 2015-08-19 18:04:34
    运维部门需要一个http服务器,来查询服务器及玩家的一些数据。 在做的过程中考虑的是两个问题: 1 这个http服务器挂在什么地方? 为了不污染pemelo的代码,做了一个httpServer的组件,在gate服务器中加载。 ...
  • java 编写简易的http服务器

    千次阅读 2019-06-05 14:40:27
    java 编写简易的http服务器 想要写一个http服务器,首先得了解http协议。这里仅介绍一下相关的知识。 1、http协议 HTTP请求报文 在请求中,HTTP报文由方法、URI、HTTP版本、HTTP首部字段等部分构成。其中方法、...
  • netty实现http服务器

    千次阅读 2017-10-21 12:08:26
    本文主要讲解如何用Netty 实现一个简单的http服务器。 1 http 请求消息 Http的请求由三部分组成:请求行、消息头、请求正文(body)。 请求行以一个方法开头,以空格分开,后面跟着请求URI和协议版本,格式为:...
  • C++socket网络编程大全实战http服务器(支持php)视频培训教程概况:本课程会同时演示在linux和windows中的编程,课程中的线程和正则表达式都使用c++提供库。本课程包含了socket网络编程常用的所有特性,包括tcp、udp...
  • 说说如何搭建 HTTP 服务器

    千次阅读 2018-06-10 11:42:46
    这里使用 Apache HTTP Server 来搭建 HTTP 服务器。 1、在搜索引擎中输入 “Apache HTTP Server 下载” 关键字,下载 Apache HTTP Server 的安装包,形如:httpd-2.2.25-win32-x86-no_ssl.msi 2、双击运行安装程序...
  • 阿帕奇HTTP服务器下载与安装

    万次阅读 多人点赞 2013-10-14 12:38:09
    阿帕奇HTTP服务器下载与安装.
  • 在很多情况下,需要在本地开启http服务器来测试。所以就需要一个简单的省事好用的http服务器。 1.简介: http-server是一个简单的零配置命令行http服务器。它对于生产使用来说是足够强大的,但它的测试,本地开发和...
  • Java 实现简单的Http服务器

    千次阅读 2018-02-02 11:11:25
    Java 实现简单的Http服务器  首先需要说明的是,这个HTTP服务器真的超级简单,简单到只有一个Java类,它只能返回一个特定的HTML文本。写这个HTTP服务器程序是为了探究Web服务器到底是如何提供HTTP服务的。  要...
  • http服务-搭建简易的http服务器

    万次阅读 2016-08-13 18:31:32
    http服务-搭建简易的http服务器仅仅实现了Post和Get,也就简单的使用了 200 OK,100-continue和发送http格式的文本而已,其实我们只要按照HTTP协议收发数据即可。先来一张做http上传功能时的意外收获,也是待会我们的...
  • HTTP服务器开发教程

    万次阅读 2010-08-07 09:42:00
    最近因为项目需要,必须自己实现一个HTTP服务器的部分功能。 需求大概是这样的,winform里使用webrowser控件显示一个本地的html页面,同时winform启动http服务,本地html页面里通过javascript使用XMLHttpRequest...
  • HTTP服务器 -- http-server 的安装与运行

    千次阅读 2019-07-18 15:10:08
    http-server 是一个简单的零配置命令行HTTP服务器, 基于 nodeJs. HttpServlet容器响应Web客户请求流程如下: 1)Web客户向Servlet容器发出Http请求; 2)Servlet容器解析Web客户的Http请求; 3)Servlet容器...
  • 文章翻译至: HTTP Server: ... ... 我们访问的每个网站都在HTTP服务器上运行。 您可能会说还有HTTPS服务器。 从技术上讲,HTTPS与HTTP相同,只是HTTPS具有更高的安全性。 许多程序员可能会对HTTP服务器的工作原理以及...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 323,521
精华内容 129,408
关键字:

http服务器