From f6a381f3767d1038ff85b36633f9acf52b645329 Mon Sep 17 00:00:00 2001 From: godotg Date: Fri, 22 Dec 2023 11:18:05 +0800 Subject: [PATCH] feat[json]: json tcp server --- .../com/zfoo/net/core/json/JsonTcpClient.java | 39 ++++++++++ .../com/zfoo/net/core/json/JsonTcpServer.java | 41 +++++++++++ .../codec/json/JsonTcpCodecHandler.java | 72 +++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 net/src/main/java/com/zfoo/net/core/json/JsonTcpClient.java create mode 100644 net/src/main/java/com/zfoo/net/core/json/JsonTcpServer.java create mode 100644 net/src/main/java/com/zfoo/net/handler/codec/json/JsonTcpCodecHandler.java diff --git a/net/src/main/java/com/zfoo/net/core/json/JsonTcpClient.java b/net/src/main/java/com/zfoo/net/core/json/JsonTcpClient.java new file mode 100644 index 00000000..bc985941 --- /dev/null +++ b/net/src/main/java/com/zfoo/net/core/json/JsonTcpClient.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.net.core.json; + +import com.zfoo.net.core.AbstractClient; +import com.zfoo.net.core.HostAndPort; +import com.zfoo.net.handler.ClientRouteHandler; +import com.zfoo.net.handler.codec.json.JsonTcpCodecHandler; +import com.zfoo.net.handler.idle.ClientIdleHandler; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.timeout.IdleStateHandler; + +/** + * @author godotg + */ +public class JsonTcpClient extends AbstractClient { + public JsonTcpClient(HostAndPort host) { + super(host); + } + + @Override + protected void initChannel(SocketChannel channel) { + channel.pipeline().addLast(new IdleStateHandler(0, 0, 60)); + channel.pipeline().addLast(new ClientIdleHandler()); + channel.pipeline().addLast(new JsonTcpCodecHandler()); + channel.pipeline().addLast(new ClientRouteHandler()); + } +} diff --git a/net/src/main/java/com/zfoo/net/core/json/JsonTcpServer.java b/net/src/main/java/com/zfoo/net/core/json/JsonTcpServer.java new file mode 100644 index 00000000..94eab943 --- /dev/null +++ b/net/src/main/java/com/zfoo/net/core/json/JsonTcpServer.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.net.core.json; + +import com.zfoo.net.core.AbstractServer; +import com.zfoo.net.core.HostAndPort; +import com.zfoo.net.handler.ServerRouteHandler; +import com.zfoo.net.handler.codec.json.JsonTcpCodecHandler; +import com.zfoo.net.handler.codec.tcp.TcpCodecHandler; +import com.zfoo.net.handler.idle.ServerIdleHandler; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.timeout.IdleStateHandler; + +/** + * @author godotg + */ +public class JsonTcpServer extends AbstractServer { + + public JsonTcpServer(HostAndPort host) { + super(host); + } + + @Override + protected void initChannel(SocketChannel channel) throws Exception { + channel.pipeline().addLast(new IdleStateHandler(0, 0, 180)); + channel.pipeline().addLast(new ServerIdleHandler()); + channel.pipeline().addLast(new JsonTcpCodecHandler()); + channel.pipeline().addLast(new ServerRouteHandler()); + } +} diff --git a/net/src/main/java/com/zfoo/net/handler/codec/json/JsonTcpCodecHandler.java b/net/src/main/java/com/zfoo/net/handler/codec/json/JsonTcpCodecHandler.java new file mode 100644 index 00000000..b3f44760 --- /dev/null +++ b/net/src/main/java/com/zfoo/net/handler/codec/json/JsonTcpCodecHandler.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.net.handler.codec.json; + +import com.zfoo.net.packet.EncodedPacketInfo; +import com.zfoo.protocol.util.IOUtils; +import com.zfoo.protocol.util.StringUtils; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; + +import java.util.List; + +import static com.zfoo.net.packet.PacketService.PACKET_HEAD_LENGTH; + +/** + * header(4byte) + protocolId(2byte) + packet + * header = body(bytes.length) + protocolId.length(2byte) + * + * @author godotg + */ +public class JsonTcpCodecHandler extends ByteToMessageCodec { + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + // 不够读一个int + if (in.readableBytes() <= PACKET_HEAD_LENGTH) { + return; + } + in.markReaderIndex(); + var length = in.readInt(); + + // 如果长度非法,则抛出异常断开连接,按照自己的使用场景指定合适的长度,防止客户端发送超大包占用带宽 + if (length < 0 || length > IOUtils.BYTES_PER_MB) { + throw new IllegalArgumentException(StringUtils.format("illegal packet [length:{}]", length)); + } + + // ByteBuf里的数据太小 + if (in.readableBytes() < length) { + in.resetReaderIndex(); + return; + } + + // readSlice和byte[]数组相比,readSlice减少了垃圾回收 + var sliceByteBuf = in.readSlice(length); + var packetInfo = JsonPacket.readDecodedPacketInfo(sliceByteBuf); + out.add(packetInfo); + } + + @Override + protected void encode(ChannelHandlerContext ctx, EncodedPacketInfo packetInfo, ByteBuf out) { + out.writeInt(PACKET_HEAD_LENGTH); + JsonPacket.writeEncodedPacketInfo(out, packetInfo); + int length = out.readableBytes(); + int packetLength = length - PACKET_HEAD_LENGTH; + out.writerIndex(0); + out.writeInt(packetLength); + out.writerIndex(length); + } + +}