添加对 Web Socket 的支持

This commit is contained in:
tursom 2019-12-06 13:05:27 +08:00
parent 1d66a0ff92
commit 53f5801d64
8 changed files with 102 additions and 5 deletions

View File

@ -10,15 +10,20 @@ import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.codec.http.HttpObjectAggregator import io.netty.handler.codec.http.HttpObjectAggregator
import io.netty.handler.codec.http.HttpRequestDecoder import io.netty.handler.codec.http.HttpServerCodec
import io.netty.handler.codec.http.HttpResponseEncoder import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler
import io.netty.handler.stream.ChunkedWriteHandler import io.netty.handler.stream.ChunkedWriteHandler
import io.netty.handler.timeout.ReadTimeoutHandler
import io.netty.handler.timeout.WriteTimeoutHandler
class NettyHttpServer( class NettyHttpServer(
override val port: Int, override val port: Int,
handler: HttpHandler<NettyHttpContent, NettyExceptionContent>, handler: HttpHandler<NettyHttpContent, NettyExceptionContent>,
bodySize: Int = 512 * 1024, bodySize: Int = 512 * 1024,
autoRun: Boolean = false autoRun: Boolean = false,
webSocketPath: String? = null,
readTimeout: Int? = null,
writeTimeout: Int? = null
) : HttpServer { ) : HttpServer {
constructor( constructor(
port: Int, port: Int,
@ -41,10 +46,24 @@ class NettyHttpServer(
.childHandler(object : ChannelInitializer<SocketChannel>() { .childHandler(object : ChannelInitializer<SocketChannel>() {
override fun initChannel(ch: SocketChannel) { override fun initChannel(ch: SocketChannel) {
ch.pipeline() ch.pipeline()
.addLast("decoder", HttpRequestDecoder()) .apply {
.addLast("encoder", HttpResponseEncoder()) if (readTimeout != null) {
addLast(ReadTimeoutHandler(readTimeout))
}
}
.apply {
if (writeTimeout != null) {
addLast(WriteTimeoutHandler(writeTimeout))
}
}
.addLast("codec", HttpServerCodec())
.addLast("aggregator", HttpObjectAggregator(bodySize)) .addLast("aggregator", HttpObjectAggregator(bodySize))
.addLast("http-chunked", ChunkedWriteHandler()) .addLast("http-chunked", ChunkedWriteHandler())
.apply {
if (webSocketPath != null) {
addLast("ws", WebSocketServerProtocolHandler(webSocketPath))
}
}
.addLast("handle", httpHandler) .addLast("handle", httpHandler)
} }
}) })

View File

@ -0,0 +1,12 @@
package cn.tursom.web.netty.ws
import cn.tursom.core.buffer.ByteBuffer
import cn.tursom.web.netty.NettyByteBuffer
import cn.tursom.web.ws.TextWebSocketFrame
class NettyTextWebSocketFrame(
@Suppress("MemberVisibilityCanBePrivate") val frame: io.netty.handler.codec.http.websocketx.TextWebSocketFrame
) : TextWebSocketFrame {
override val text: String by lazy { data.toString(data.readable) }
override val data: ByteBuffer = NettyByteBuffer(frame.content())
}

View File

@ -0,0 +1,15 @@
package cn.tursom.web.netty.ws
import cn.tursom.web.netty.NettyExceptionContent
import cn.tursom.web.ws.WebSocketHandler
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.codec.http.websocketx.WebSocketFrame
class NettyWebSocketHandler(
val handler: WebSocketHandler<NettyExceptionContent>
) : SimpleChannelInboundHandler<WebSocketFrame>() {
override fun channelRead0(ctx: ChannelHandlerContext?, msg: WebSocketFrame?) {
}
}

View File

@ -0,0 +1,9 @@
package cn.tursom.web.netty.ws
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.http.FullHttpRequest
class NettyWsHttpContent(
val ctx: ChannelHandlerContext,
val msg: FullHttpRequest
)

View File

@ -0,0 +1,5 @@
package cn.tursom.web.ws
interface TextWebSocketFrame : WebSocketFrame {
val text: String
}

View File

@ -0,0 +1,6 @@
package cn.tursom.web.ws
interface WebSocketContent {
val frame: WebSocketFrame
fun write(frame: WebSocketFrame)
}

View File

@ -0,0 +1,7 @@
package cn.tursom.web.ws
import cn.tursom.core.buffer.ByteBuffer
interface WebSocketFrame {
val data: ByteBuffer
}

View File

@ -0,0 +1,24 @@
package cn.tursom.web.ws
import cn.tursom.web.ExceptionContent
import cn.tursom.web.HttpHandler
interface WebSocketHandler<T : ExceptionContent> : HttpHandler<WsHttpContent, T> {
override fun handle(content: WsHttpContent) {
val frame = content.frame
when (frame) {
is TextWebSocketFrame -> {
handle(content, frame)
}
else -> {
}
}
handle(content, frame)
}
fun handle(content: WsHttpContent, frame: TextWebSocketFrame) {
}
fun handle(content: WsHttpContent, frame: WebSocketFrame) {
}
}