1. 程式人生 > >Netty程式設計——簡單的http伺服器

Netty程式設計——簡單的http伺服器

經常看到Tornado的監聽埠,身為Javaista,tomcat對底層封裝極其喪心病狂,計劃開始手擼一個基於Netty的http伺服器,並不斷完善,順便學習NIO和RPC

第一個超級簡單,hello world,本次編碼使用kotlin實現,具體和Java沒有太大區別,接下來從netty各個元件開始學習完善優化

  1. channel、eventloop和channelfuture
  2. netty資料容器
  3. 編解碼
  4. 多執行緒
  5. 網路協議
package com.kotlin.server

import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.close
import io.netty.handler.codec.http.HttpRequest
import io.netty.bootstrap.ServerBootstrap
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInboundHandlerAdapter
import io.netty.channel.ChannelInitializer
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import java.io.UnsupportedEncodingException
import io.netty.channel.socket.SocketChannel
import io.netty.handler.codec.http.*


object HttpServer {

    @Throws(InterruptedException::class)
    @JvmStatic
    fun main(args: Array<String>) {
        val bossGroup = NioEventLoopGroup()
        val workerGroup = NioEventLoopGroup()
        try {
            val b = ServerBootstrap()
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel::class.java)
                    .childHandler(object : ChannelInitializer<SocketChannel>() {
                        @Throws(Exception::class)
                        override fun initChannel(ch: SocketChannel) {
                            val pipeline = ch.pipeline()
                            pipeline.addLast(HttpServerCodec())
                            pipeline.addLast(HttpServerHandler())
                        }
                    })
            val f = b.bind(8080).sync()
            f.channel().closeFuture().sync()
        } finally {
            workerGroup.shutdownGracefully()
            bossGroup.shutdownGracefully()
        }
    }
}

internal class HttpServerHandler : ChannelInboundHandlerAdapter() {

    @Throws(UnsupportedEncodingException::class)
    override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {

        if (msg is HttpRequest) {

            // 請求,解碼器將請求轉換成HttpRequest物件
           // val request:HttpRequest = msg
            // 獲取請求引數
            val queryStringDecoder = QueryStringDecoder(msg.uri())
            var name = "World"
//            if (queryStringDecoder.parameters().get("name") != null) {
//                name = queryStringDecoder.parameters().get("name").get(0)
//            }

            // 響應HTML
            val responseHtml = "<html><body>Hello, $name</body></html>"
            val responseBytes = responseHtml.toByteArray(charset("UTF-8"))
            val contentLength = responseBytes.size

            // 構造FullHttpResponse物件,FullHttpResponse包含message body
            val response = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseBytes))
            response.headers().set("Content-Type", "text/html; charset=utf-8")
            response.headers().set("Content-Length", Integer.toString(contentLength))

            ctx.writeAndFlush(response)
        }
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        cause.printStackTrace()
        ctx.close()
    }
}
這樣粗淺低層次的POC正對應著本人水平~~