feat[json]: json tcp server

This commit is contained in:
godotg
2023-12-22 11:18:05 +08:00
parent 9045c25174
commit f6a381f376
3 changed files with 152 additions and 0 deletions
@@ -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<SocketChannel> {
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());
}
}
@@ -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<SocketChannel> {
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());
}
}
@@ -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<EncodedPacketInfo> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> 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);
}
}