feat: optimize websocket

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
2020-11-13 09:40:47 +08:00
parent d769a9c8ca
commit 7f5929bc87
10 changed files with 195 additions and 126 deletions

View File

@@ -1,40 +1,40 @@
import { EventEmitter } from 'events'
import { SocketIO } from '../socket-io/interfaces';
import { AttributeKeys } from './constants';
import { SocketIO } from '../socket-io/interfaces'
import { AttributeKeys } from './constants'
const TextWebSocketFrame = Java.type('io.netty.handler.codec.http.websocketx.TextWebSocketFrame')
export class NettyClient extends EventEmitter implements SocketIO.EngineSocket {
private _id: string;
private _id: string
private channel: any
server: any;
readyState: string;
remoteAddress: string;
upgraded: boolean;
request: any;
transport: any;
server: any
readyState: string
remoteAddress: string
upgraded: boolean
request: any
transport: any
constructor(server: any, channel: any) {
super();
this.server = server;
this.readyState = 'open';
super()
this.server = server
this.readyState = 'open'
this.remoteAddress = channel.remoteAddress() + ''
this.upgraded = true;
this.request = channel.attr(AttributeKeys.Request).get();
this.transport = null;
this.upgraded = true
this.request = channel.attr(AttributeKeys.Request).get()
this.transport = null
this.channel = channel;
this._id = channel.id();
this.channel = channel
this._id = channel.id() + ''
}
get id() {
return this._id;
return this._id
}
send(text: string) {
this.channel.writeAndFlush(new TextWebSocketFrame(text))
}
close() {
this.channel.close();
this.channel.close()
}
}

View File

@@ -9,14 +9,14 @@ import { WebSocketDetect } from './websocket_detect'
import { WebSocketHandler } from './websocket_handler'
class NettyWebSocketServer extends EventEmitter {
private pipeline: any;
private allClients: { [key: string]: NettyClient };
private pipeline: any
private clients: Map<string, NettyClient>
constructor(pipeline: any, options: ServerOptions) {
super()
this.allClients = {};
this.pipeline = pipeline;
let connectEvent = options.event;
this.clients = new Map()
this.pipeline = pipeline
let connectEvent = options.event
try { this.pipeline.remove(Keys.Detect) } catch (error) { }
this.pipeline.addFirst(Keys.Detect, new WebSocketDetect(connectEvent).getHandler())
connectEvent.on(ServerEvent.detect, (ctx, channel) => {
@@ -24,22 +24,42 @@ class NettyWebSocketServer extends EventEmitter {
ctx.fireChannelRead(channel)
})
connectEvent.on(ServerEvent.connect, (ctx) => {
let cid = ctx?.channel().id() + ''
let nettyClient = new NettyClient(this, ctx.channel())
this.allClients[nettyClient.id] = nettyClient
this.clients.set(cid, nettyClient)
this.emit(ServerEvent.connect, nettyClient)
})
connectEvent.on(ServerEvent.message, (ctx, msg) => {
this.emit(ServerEvent.message, this.allClients[ctx.channel().id()], msg.text())
let cid = ctx?.channel().id() + ''
if (this.clients.has(cid)) {
this.emit(ServerEvent.message, this.clients.get(cid), msg.text())
} else {
console.error(`unknow client ${ctx} reciver message ${msg.text()}`)
}
})
connectEvent.on(ServerEvent.disconnect, (ctx, cause) => {
let cid = ctx?.channel().id() + ''
if (this.clients.has(cid)) {
this.emit(ServerEvent.disconnect, this.clients.get(cid), cause)
} else {
console.error(`unknow client ${ctx} disconnect cause ${cause}`)
}
})
connectEvent.on(ServerEvent.error, (ctx, cause) => {
this.emit(ServerEvent.error, this.allClients[ctx.channel().id()], cause)
let cid = ctx?.channel().id() + ''
if (this.clients.has(cid)) {
this.emit(ServerEvent.error, this.clients.get(cid), cause)
} else {
console.error(`unknow client ${ctx} cause error ${cause}`)
console.ex(cause)
}
})
}
close() {
if (this.pipeline.names().contains(Keys.Detect)) {
this.pipeline.remove(Keys.Detect)
}
Object.values(this.allClients).forEach(client => client.close())
this.clients.forEach(client => client.close())
}
}

View File

@@ -3,15 +3,19 @@ import { WebSocketHandlerAdapter } from "../netty"
import { ServerEvent } from '../socket-io/constants'
export class WebSocketDetect extends WebSocketHandlerAdapter {
private event: EventEmitter;
private event: EventEmitter
constructor(event: EventEmitter) {
super()
this.event = event;
this.event = event
}
channelRead(ctx: any, channel: any) {
this.event.emit(ServerEvent.detect, ctx, channel);
this.event.emit(ServerEvent.detect, ctx, channel)
}
channelUnregistered(ctx: any) {
this.event.emit(ServerEvent.disconnect, ctx, 'client disconnect')
ctx.fireChannelUnregistered()
}
exceptionCaught(ctx: any, cause: Error) {
this.event.emit(ServerEvent.error, ctx, cause);
this.event.emit(ServerEvent.error, ctx, cause)
}
}

View File

@@ -13,10 +13,10 @@ const HttpObjectAggregator = Java.type('io.netty.handler.codec.http.HttpObjectAg
const WebSocketServerProtocolHandler = Java.type('io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler')
export class WebSocketHandler extends WebSocketHandlerAdapter {
private options: ServerOptions;
private options: ServerOptions
constructor(options: ServerOptions) {
super()
this.options = options;
this.options = options
}
channelRead(ctx: any, msg: any) {
msg.markReaderIndex()
@@ -32,6 +32,7 @@ export class WebSocketHandler extends WebSocketHandlerAdapter {
pipeline.addLast('chunk', new ChunkedWriteHandler())
pipeline.addLast('httpobj', new HttpObjectAggregator(64 * 1024))
pipeline.addLast('http_request', new HttpRequestHandler(this.options).getHandler())
// this.options.path, null, false, 655360, false, true, false, 10000
pipeline.addLast('websocket', new WebSocketServerProtocolHandler(this.options.path, true))
pipeline.addLast('websocket_handler', new TextWebSocketFrameHandler(this.options).getHandler())
}
@@ -39,6 +40,12 @@ export class WebSocketHandler extends WebSocketHandlerAdapter {
msg.resetReaderIndex()
ctx.fireChannelRead(msg)
}
channelUnregistered(ctx: any) {
this.options.event.emit(ServerEvent.disconnect, ctx, 'client disconnect')
ctx.fireChannelUnregistered()
}
exceptionCaught(ctx: any, cause: Error) {
this.options.event.emit(ServerEvent.error, ctx, cause)
}