diff --git a/net/src/main/java/com/zfoo/net/core/AbstractClient.java b/net/src/main/java/com/zfoo/net/core/AbstractClient.java index 8f392b88..8d6438cc 100644 --- a/net/src/main/java/com/zfoo/net/core/AbstractClient.java +++ b/net/src/main/java/com/zfoo/net/core/AbstractClient.java @@ -38,16 +38,16 @@ import org.slf4j.LoggerFactory; */ public abstract class AbstractClient implements IClient { - private static final Logger logger = LoggerFactory.getLogger(AbstractClient.class); + protected static final Logger logger = LoggerFactory.getLogger(AbstractClient.class); - private static final EventLoopGroup nioEventLoopGroup = Epoll.isAvailable() + protected static final EventLoopGroup nioEventLoopGroup = Epoll.isAvailable() ? new EpollEventLoopGroup(Runtime.getRuntime().availableProcessors() + 1, new DefaultThreadFactory("netty-client", true)) : new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() + 1, new DefaultThreadFactory("netty-client", true)); - private String hostAddress; - private int port; + protected String hostAddress; + protected int port; - private Bootstrap bootstrap; + protected Bootstrap bootstrap; public AbstractClient(HostAndPort host) { this.hostAddress = host.getHost(); diff --git a/net/src/main/java/com/zfoo/net/core/AbstractServer.java b/net/src/main/java/com/zfoo/net/core/AbstractServer.java index 51ea788b..dd004724 100644 --- a/net/src/main/java/com/zfoo/net/core/AbstractServer.java +++ b/net/src/main/java/com/zfoo/net/core/AbstractServer.java @@ -37,21 +37,21 @@ public abstract class AbstractServer implements IServer { private static final Logger logger = LoggerFactory.getLogger(AbstractServer.class); // 所有的服务器都可以在这个列表中取到 - private static final List allServers = new ArrayList<>(1); + protected static final List allServers = new ArrayList<>(1); - private String hostAddress; - private int port; + protected String hostAddress; + protected int port; // 配置服务端nio线程组,服务端接受客户端连接 private EventLoopGroup bossGroup; // SocketChannel的网络读写 - private EventLoopGroup workerGroup; + protected EventLoopGroup workerGroup; - private ChannelFuture channelFuture; + protected ChannelFuture channelFuture; - private Channel channel; + protected Channel channel; public AbstractServer(HostAndPort host) { this.hostAddress = host.getHost(); @@ -79,7 +79,7 @@ public abstract class AbstractServer implements IServer { bootstrap.group(bossGroup, workerGroup) .channel(Epoll.isAvailable() ? EpollServerSocketChannel.class : NioServerSocketChannel.class) .option(ChannelOption.SO_REUSEADDR, true) - .option(ChannelOption.TCP_NODELAY, true) + .childOption(ChannelOption.TCP_NODELAY, true) .childHandler(channelChannelInitializer); // 绑定端口,同步等待成功 // channelFuture = bootstrap.bind(hostAddress, port).sync(); @@ -122,6 +122,9 @@ public abstract class AbstractServer implements IServer { } public synchronized static void shutdownEventLoopGracefully(EventExecutorGroup executor) { + if (executor == null) { + return; + } try { if (executor.isShutdown() || executor.isTerminated()) { executor.shutdownGracefully(); diff --git a/net/src/main/java/com/zfoo/net/core/gateway/GatewayServer.java b/net/src/main/java/com/zfoo/net/core/gateway/GatewayServer.java index 78132816..fb128c21 100644 --- a/net/src/main/java/com/zfoo/net/core/gateway/GatewayServer.java +++ b/net/src/main/java/com/zfoo/net/core/gateway/GatewayServer.java @@ -42,15 +42,15 @@ public class GatewayServer extends AbstractServer { @Override public ChannelInitializer channelChannelInitializer() { - return new GatewayChannelHandler(packetFilter); + return new ChannelHandlerInitializer(packetFilter); } - private static class GatewayChannelHandler extends ChannelInitializer { + private static class ChannelHandlerInitializer extends ChannelInitializer { private BiFunction packetFilter; - public GatewayChannelHandler(BiFunction packetFilter) { + public ChannelHandlerInitializer(BiFunction packetFilter) { this.packetFilter = packetFilter; } diff --git a/net/src/main/java/com/zfoo/net/core/gateway/WebsocketGatewayServer.java b/net/src/main/java/com/zfoo/net/core/gateway/WebsocketGatewayServer.java index d253491d..03f204f2 100644 --- a/net/src/main/java/com/zfoo/net/core/gateway/WebsocketGatewayServer.java +++ b/net/src/main/java/com/zfoo/net/core/gateway/WebsocketGatewayServer.java @@ -46,15 +46,15 @@ public class WebsocketGatewayServer extends AbstractServer { @Override public ChannelInitializer channelChannelInitializer() { - return new GatewayChannelHandler(packetFilter); + return new ChannelHandlerInitializer(packetFilter); } - private static class GatewayChannelHandler extends ChannelInitializer { + private static class ChannelHandlerInitializer extends ChannelInitializer { private BiFunction packetFilter; - public GatewayChannelHandler(BiFunction packetFilter) { + public ChannelHandlerInitializer(BiFunction packetFilter) { this.packetFilter = packetFilter; } diff --git a/net/src/main/java/com/zfoo/net/core/gateway/WebsocketSslGatewayServer.java b/net/src/main/java/com/zfoo/net/core/gateway/WebsocketSslGatewayServer.java index fde244df..24ca86d5 100644 --- a/net/src/main/java/com/zfoo/net/core/gateway/WebsocketSslGatewayServer.java +++ b/net/src/main/java/com/zfoo/net/core/gateway/WebsocketSslGatewayServer.java @@ -61,16 +61,16 @@ public class WebsocketSslGatewayServer extends AbstractServer { @Override public ChannelInitializer channelChannelInitializer() { - return new GatewayChannelHandler(sslContext, packetFilter); + return new ChannelHandlerInitializer(sslContext, packetFilter); } - private static class GatewayChannelHandler extends ChannelInitializer { + private static class ChannelHandlerInitializer extends ChannelInitializer { private SslContext sslContext; private BiFunction packetFilter; - public GatewayChannelHandler(SslContext sslContext, BiFunction packetFilter) { + public ChannelHandlerInitializer(SslContext sslContext, BiFunction packetFilter) { this.sslContext = sslContext; this.packetFilter = packetFilter; } diff --git a/net/src/main/java/com/zfoo/net/core/tcp/TcpClient.java b/net/src/main/java/com/zfoo/net/core/tcp/TcpClient.java index bd8435b8..84d5da75 100644 --- a/net/src/main/java/com/zfoo/net/core/tcp/TcpClient.java +++ b/net/src/main/java/com/zfoo/net/core/tcp/TcpClient.java @@ -35,11 +35,11 @@ public class TcpClient extends AbstractClient { @Override public ChannelInitializer channelChannelInitializer() { - return new TcpChannelInitHandler(); + return new ChannelHandlerInitializer(); } - private static class TcpChannelInitHandler extends ChannelInitializer { + private static class ChannelHandlerInitializer extends ChannelInitializer { @Override protected void initChannel(SocketChannel channel) { channel.pipeline().addLast(new IdleStateHandler(0, 0, 60)); diff --git a/net/src/main/java/com/zfoo/net/core/tcp/TcpServer.java b/net/src/main/java/com/zfoo/net/core/tcp/TcpServer.java index 83826bc1..8a729e79 100644 --- a/net/src/main/java/com/zfoo/net/core/tcp/TcpServer.java +++ b/net/src/main/java/com/zfoo/net/core/tcp/TcpServer.java @@ -34,11 +34,11 @@ public class TcpServer extends AbstractServer { @Override public ChannelInitializer channelChannelInitializer() { - return new TcpChannelHandler(); + return new ChannelHandlerInitializer(); } - private static class TcpChannelHandler extends ChannelInitializer { + private static class ChannelHandlerInitializer extends ChannelInitializer { @Override protected void initChannel(SocketChannel channel) { channel.pipeline().addLast(new IdleStateHandler(0, 0, 180)); diff --git a/net/src/main/java/com/zfoo/net/core/udp/UdpClient.java b/net/src/main/java/com/zfoo/net/core/udp/UdpClient.java new file mode 100644 index 00000000..2c353e2a --- /dev/null +++ b/net/src/main/java/com/zfoo/net/core/udp/UdpClient.java @@ -0,0 +1,89 @@ +/* + * 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.udp; + +import com.zfoo.net.NetContext; +import com.zfoo.net.core.AbstractClient; +import com.zfoo.net.handler.BaseDispatcherHandler; +import com.zfoo.net.handler.ClientDispatcherHandler; +import com.zfoo.net.handler.codec.udp.UdpCodecHandler; +import com.zfoo.net.session.model.Session; +import com.zfoo.protocol.exception.ExceptionUtils; +import com.zfoo.util.net.HostAndPort; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.socket.nio.NioDatagramChannel; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpClient extends AbstractClient { + + public UdpClient(HostAndPort host) { + super(host); + } + + @Override + public synchronized Session start() { + try { + this.bootstrap = new Bootstrap(); + this.bootstrap.group(nioEventLoopGroup) + .channel(Epoll.isAvailable() ? EpollDatagramChannel.class : NioDatagramChannel.class) + .option(ChannelOption.SO_BROADCAST, true) + .handler(new ChannelHandlerInitializer()); + + // bind(0)随机选择一个端口 + var channelFuture = bootstrap.bind(0).sync(); + channelFuture.syncUninterruptibly(); + + if (channelFuture.isSuccess()) { + if (channelFuture.channel().isActive()) { + var channel = channelFuture.channel(); + var session = BaseDispatcherHandler.initChannel(channel); + NetContext.getSessionManager().addClientSession(session); + logger.info("UdpClient started at [{}]", channel.localAddress()); + return session; + } + } else if (channelFuture.cause() != null) { + logger.error(ExceptionUtils.getMessage(channelFuture.cause())); + } else { + logger.error("启动客户端[client:{}]未知错误", this); + } + } catch (Exception e) { + logger.error(ExceptionUtils.getMessage(e)); + } + return null; + } + + @Override + public ChannelInitializer channelChannelInitializer() { + return new ChannelHandlerInitializer(); + } + + + private static class ChannelHandlerInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) { + channel.pipeline().addLast(new UdpCodecHandler()); + channel.pipeline().addLast(new ClientDispatcherHandler()); + } + } + + +} diff --git a/net/src/main/java/com/zfoo/net/core/udp/UdpServer.java b/net/src/main/java/com/zfoo/net/core/udp/UdpServer.java new file mode 100644 index 00000000..4b0a2506 --- /dev/null +++ b/net/src/main/java/com/zfoo/net/core/udp/UdpServer.java @@ -0,0 +1,76 @@ +/* + * 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.udp; + +import com.zfoo.net.core.AbstractServer; +import com.zfoo.net.handler.ServerDispatcherHandler; +import com.zfoo.net.handler.codec.udp.UdpCodecHandler; +import com.zfoo.util.net.HostAndPort; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioDatagramChannel; +import io.netty.util.concurrent.DefaultThreadFactory; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpServer extends AbstractServer { + + public UdpServer(HostAndPort host) { + super(host); + } + + @Override + public void start() { + var cpuNum = Runtime.getRuntime().availableProcessors(); + + // 配置服务端nio线程组 + workerGroup = Epoll.isAvailable() + ? new EpollEventLoopGroup(cpuNum * 2, new DefaultThreadFactory("netty-worker", true)) + : new NioEventLoopGroup(cpuNum * 2, new DefaultThreadFactory("netty-worker", true)); + + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(workerGroup) + .channel(Epoll.isAvailable() ? EpollDatagramChannel.class : NioDatagramChannel.class) + .option(ChannelOption.SO_BROADCAST, true) + .handler(channelChannelInitializer()); + + // 异步 + channelFuture = bootstrap.bind(hostAddress, port); + channelFuture.syncUninterruptibly(); + channel = channelFuture.channel(); + + allServers.add(this); + } + + @Override + public ChannelInitializer channelChannelInitializer() { + return new ChannelHandlerInitializer(); + } + + + private static class ChannelHandlerInitializer extends ChannelInitializer { + @Override + protected void initChannel(Channel channel) { + channel.pipeline().addLast(new UdpCodecHandler()); + channel.pipeline().addLast(new ServerDispatcherHandler()); + } + } +} diff --git a/net/src/main/java/com/zfoo/net/core/websocket/WebsocketServer.java b/net/src/main/java/com/zfoo/net/core/websocket/WebsocketServer.java index 64881cfe..ac59c94d 100644 --- a/net/src/main/java/com/zfoo/net/core/websocket/WebsocketServer.java +++ b/net/src/main/java/com/zfoo/net/core/websocket/WebsocketServer.java @@ -37,11 +37,11 @@ public class WebsocketServer extends AbstractServer { @Override public ChannelInitializer channelChannelInitializer() { - return new WebSocketServerInitializer(); + return new ChannelHandlerInitializer(); } - public class WebSocketServerInitializer extends ChannelInitializer { + public static class ChannelHandlerInitializer extends ChannelInitializer { @Override public void initChannel(SocketChannel channel) { @@ -59,7 +59,6 @@ public class WebsocketServer extends AbstractServer { pipeline.addLast(new WebSocketCodecHandler()); pipeline.addLast(new ServerDispatcherHandler()); } - } } diff --git a/net/src/main/java/com/zfoo/net/dispatcher/manager/PacketBus.java b/net/src/main/java/com/zfoo/net/dispatcher/manager/PacketBus.java index 7a8c2f1c..dfb59197 100644 --- a/net/src/main/java/com/zfoo/net/dispatcher/manager/PacketBus.java +++ b/net/src/main/java/com/zfoo/net/dispatcher/manager/PacketBus.java @@ -20,6 +20,7 @@ import com.zfoo.net.dispatcher.model.vo.IPacketReceiver; import com.zfoo.net.dispatcher.model.vo.PacketReceiverDefinition; import com.zfoo.net.packet.model.GatewayPacketAttachment; import com.zfoo.net.packet.model.IPacketAttachment; +import com.zfoo.net.packet.model.UdpPacketAttachment; import com.zfoo.net.packet.service.PacketService; import com.zfoo.net.session.model.Session; import com.zfoo.protocol.IPacket; @@ -109,7 +110,7 @@ public abstract class PacketBus { // 如果以Ask结尾的请求,那么attachment不能为GatewayAttachment if (attachmentClazz != null) { if (packetName.endsWith(PacketService.NET_REQUEST_SUFFIX)) { - AssertionUtils.isTrue(attachmentClazz.equals(GatewayPacketAttachment.class) + AssertionUtils.isTrue(attachmentClazz.equals(GatewayPacketAttachment.class) || attachmentClazz.equals(UdpPacketAttachment.class) , "[class:{}] [method:{}] [packet:{}] must use [attachment:{}]!", bean.getClass().getName(), methodName, packetName, GatewayPacketAttachment.class.getCanonicalName()); } else if (packetName.endsWith(PacketService.NET_ASK_SUFFIX)) { AssertionUtils.isTrue(!attachmentClazz.equals(GatewayPacketAttachment.class) diff --git a/net/src/main/java/com/zfoo/net/handler/codec/udp/UdpCodecHandler.java b/net/src/main/java/com/zfoo/net/handler/codec/udp/UdpCodecHandler.java new file mode 100644 index 00000000..a1fb006a --- /dev/null +++ b/net/src/main/java/com/zfoo/net/handler/codec/udp/UdpCodecHandler.java @@ -0,0 +1,103 @@ +/* + * 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.udp; + +import com.zfoo.net.NetContext; +import com.zfoo.net.packet.model.DecodedPacketInfo; +import com.zfoo.net.packet.model.EncodedPacketInfo; +import com.zfoo.net.packet.model.UdpPacketAttachment; +import com.zfoo.net.packet.service.PacketService; +import com.zfoo.net.util.SessionUtils; +import com.zfoo.protocol.util.JsonUtils; +import com.zfoo.protocol.util.StringUtils; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramPacket; +import io.netty.handler.codec.MessageToMessageCodec; +import io.netty.util.ReferenceCountUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetSocketAddress; +import java.util.List; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpCodecHandler extends MessageToMessageCodec { + + private static final Logger logger = LoggerFactory.getLogger(UdpCodecHandler.class); + + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List list) { + ByteBuf in = datagramPacket.content(); + + // 不够读一个int + if (in.readableBytes() <= PacketService.PACKET_HEAD_LENGTH) { + return; + } + + in.markReaderIndex(); + var length = in.readInt(); + + // 如果长度非法,则抛出异常断开连接 + if (length < 0) { + throw new IllegalArgumentException(StringUtils.format("[session:{}]的包头长度[length:{}]非法" + , SessionUtils.sessionInfo(channelHandlerContext), length)); + } + + // ByteBuf里的数据太小 + if (in.readableBytes() < length) { + in.resetReaderIndex(); + return; + } + + ByteBuf tmpByteBuf = null; + try { + tmpByteBuf = in.readRetainedSlice(length); + DecodedPacketInfo packetInfo = NetContext.getPacketService().read(tmpByteBuf); + var sender = datagramPacket.sender(); + packetInfo.setPacketAttachment(UdpPacketAttachment.valueOf(sender.getHostString(), sender.getPort())); + list.add(packetInfo); + } catch (Exception e) { + logger.error("exception异常", e); + throw e; + } catch (Throwable t) { + logger.error("throwable错误", t); + throw t; + } finally { + ReferenceCountUtil.release(tmpByteBuf); + } + } + + @Override + protected void encode(ChannelHandlerContext channelHandlerContext, EncodedPacketInfo out, List list) { + try { + ByteBuf byteBuf = Unpooled.directBuffer(); + byteBuf.clear(); + + var udpPacketAttachment = (UdpPacketAttachment) out.getPacketAttachment(); + + NetContext.getPacketService().write(byteBuf, out.getPacket(), out.getPacketAttachment()); + list.add(new DatagramPacket(byteBuf, new InetSocketAddress(udpPacketAttachment.getHost(), udpPacketAttachment.getPort()))); + } catch (Exception e) { + logger.error("[{}]编码exception异常", JsonUtils.object2String(out), e); + throw e; + } catch (Throwable t) { + logger.error("[{}]编码throwable错误", JsonUtils.object2String(out), t); + throw t; + } + } +} diff --git a/net/src/main/java/com/zfoo/net/packet/model/NoAnswerAttachment.java b/net/src/main/java/com/zfoo/net/packet/model/NoAnswerAttachment.java index 651bcaf3..de118d08 100644 --- a/net/src/main/java/com/zfoo/net/packet/model/NoAnswerAttachment.java +++ b/net/src/main/java/com/zfoo/net/packet/model/NoAnswerAttachment.java @@ -21,7 +21,7 @@ package com.zfoo.net.packet.model; */ public class NoAnswerAttachment implements IPacketAttachment { - public static final transient short PROTOCOL_ID = 2; + public static final transient short PROTOCOL_ID = 3; /** * 用来在TaskManage中计算一致性hash的参数 diff --git a/net/src/main/java/com/zfoo/net/packet/model/PacketAttachmentType.java b/net/src/main/java/com/zfoo/net/packet/model/PacketAttachmentType.java index 49622596..98e3933e 100644 --- a/net/src/main/java/com/zfoo/net/packet/model/PacketAttachmentType.java +++ b/net/src/main/java/com/zfoo/net/packet/model/PacketAttachmentType.java @@ -37,10 +37,16 @@ public enum PacketAttachmentType { */ GATEWAY_PACKET((byte) 2, GatewayPacketAttachment.class), + /** + * udp消息的附加包 + */ + UDP_PACKET((byte) 3, NoAnswerAttachment.class), + /** * 无返回消息的附加包 */ - NO_ANSWER_PACKET((byte) 3, NoAnswerAttachment.class), + NO_ANSWER_PACKET((byte) 4, NoAnswerAttachment.class), + ; diff --git a/net/src/main/java/com/zfoo/net/packet/model/UdpPacketAttachment.java b/net/src/main/java/com/zfoo/net/packet/model/UdpPacketAttachment.java new file mode 100644 index 00000000..9ccecd40 --- /dev/null +++ b/net/src/main/java/com/zfoo/net/packet/model/UdpPacketAttachment.java @@ -0,0 +1,66 @@ +/* + * 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.packet.model; + +import com.zfoo.util.math.RandomUtils; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpPacketAttachment implements IPacketAttachment { + + public static final transient short PROTOCOL_ID = 2; + + private String host; + private int port; + + public static UdpPacketAttachment valueOf(String host, int port) { + var attachment = new UdpPacketAttachment(); + attachment.host = host; + attachment.port = port; + return attachment; + } + + @Override + public PacketAttachmentType packetType() { + return PacketAttachmentType.UDP_PACKET; + } + + @Override + public int executorConsistentHash() { + return RandomUtils.randomInt(); + } + + @Override + public short protocolId() { + return PROTOCOL_ID; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/net/src/test/java/com/zfoo/net/core/tcp/client/controller/TcpClientPacketController.java b/net/src/test/java/com/zfoo/net/core/tcp/client/TcpClientPacketController.java similarity index 95% rename from net/src/test/java/com/zfoo/net/core/tcp/client/controller/TcpClientPacketController.java rename to net/src/test/java/com/zfoo/net/core/tcp/client/TcpClientPacketController.java index b6cd262e..73af5c8d 100644 --- a/net/src/test/java/com/zfoo/net/core/tcp/client/controller/TcpClientPacketController.java +++ b/net/src/test/java/com/zfoo/net/core/tcp/client/TcpClientPacketController.java @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and limitations under the License. */ -package com.zfoo.net.core.tcp.client.controller; +package com.zfoo.net.core.tcp.client; import com.zfoo.net.dispatcher.model.anno.PacketReceiver; import com.zfoo.net.packet.SM_Int; diff --git a/net/src/test/java/com/zfoo/net/core/tcp/server/controller/TcpServerPacketController.java b/net/src/test/java/com/zfoo/net/core/tcp/server/TcpServerPacketController.java similarity index 98% rename from net/src/test/java/com/zfoo/net/core/tcp/server/controller/TcpServerPacketController.java rename to net/src/test/java/com/zfoo/net/core/tcp/server/TcpServerPacketController.java index 1a212a8c..de4e7537 100644 --- a/net/src/test/java/com/zfoo/net/core/tcp/server/controller/TcpServerPacketController.java +++ b/net/src/test/java/com/zfoo/net/core/tcp/server/TcpServerPacketController.java @@ -1,6 +1,5 @@ /* * 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 * @@ -11,7 +10,7 @@ * See the License for the specific language governing permissions and limitations under the License. */ -package com.zfoo.net.core.tcp.server.controller; +package com.zfoo.net.core.tcp.server; import com.zfoo.net.NetContext; import com.zfoo.net.dispatcher.model.anno.PacketReceiver; diff --git a/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientPacketController.java b/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientPacketController.java new file mode 100644 index 00000000..1f0662b4 --- /dev/null +++ b/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientPacketController.java @@ -0,0 +1,38 @@ +/* + * 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.udp.client; + +import com.zfoo.net.dispatcher.model.anno.PacketReceiver; +import com.zfoo.net.packet.model.UdpPacketAttachment; +import com.zfoo.net.packet.udp.UdpHelloResponse; +import com.zfoo.net.session.model.Session; +import com.zfoo.protocol.util.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * @author jaysunxiao + * @version 3.0 + */ +@Component +public class UdpClientPacketController { + + private static final Logger logger = LoggerFactory.getLogger(UdpClientPacketController.class); + + @PacketReceiver + public void atUdpHelloResponse(Session session, UdpHelloResponse response, UdpPacketAttachment attachment) { + logger.info("udp client receive [packet:{}] from server", JsonUtils.object2String(response)); + } + +} diff --git a/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientTest.java b/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientTest.java new file mode 100644 index 00000000..0cfd1aaa --- /dev/null +++ b/net/src/test/java/com/zfoo/net/core/udp/client/UdpClientTest.java @@ -0,0 +1,47 @@ +/* + * 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.udp.client; + +import com.zfoo.net.NetContext; +import com.zfoo.net.core.udp.UdpClient; +import com.zfoo.net.packet.model.UdpPacketAttachment; +import com.zfoo.net.packet.udp.UdpHelloRequest; +import com.zfoo.util.ThreadUtils; +import com.zfoo.util.net.HostAndPort; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author jaysunxiao + * @version 3.0 + */ +@Ignore +public class UdpClientTest { + + @Test + public void startClientTest() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("client_config.xml"); + var client = new UdpClient(HostAndPort.valueOf(NetContext.getConfigManager().getLocalConfig().getHostConfig().getAddressMap().get("server0"))); + + var session = client.start(); + + var request = new UdpHelloRequest(); + request.setMessage("Hello, this is the udp client!"); + + NetContext.getDispatcher().send(session, request, UdpPacketAttachment.valueOf("127.0.0.1", 9000)); + + ThreadUtils.sleep(Long.MAX_VALUE); + } + +} diff --git a/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerPacketController.java b/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerPacketController.java new file mode 100644 index 00000000..28e16f25 --- /dev/null +++ b/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerPacketController.java @@ -0,0 +1,45 @@ +/* + * 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.udp.server; + +import com.zfoo.net.NetContext; +import com.zfoo.net.dispatcher.model.anno.PacketReceiver; +import com.zfoo.net.packet.model.UdpPacketAttachment; +import com.zfoo.net.packet.udp.UdpHelloRequest; +import com.zfoo.net.packet.udp.UdpHelloResponse; +import com.zfoo.net.session.model.Session; +import com.zfoo.protocol.util.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * @author jaysunxiao + * @version 3.0 + */ +@Component +public class UdpServerPacketController { + + private static final Logger logger = LoggerFactory.getLogger(UdpServerPacketController.class); + + @PacketReceiver + public void atUdpHelloRequest(Session session, UdpHelloRequest request, UdpPacketAttachment attachment) { + logger.info("udp server receive [packet:{}] from client", JsonUtils.object2String(request)); + + var response = new UdpHelloResponse(); + response.setMessage("Hello, this is the udp server!"); + + NetContext.getDispatcher().send(session, response, attachment); + } + +} diff --git a/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerTest.java b/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerTest.java new file mode 100644 index 00000000..1b803eb7 --- /dev/null +++ b/net/src/test/java/com/zfoo/net/core/udp/server/UdpServerTest.java @@ -0,0 +1,38 @@ +/* + * 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.udp.server; + +import com.zfoo.net.NetContext; +import com.zfoo.net.core.udp.UdpServer; +import com.zfoo.util.ThreadUtils; +import com.zfoo.util.net.HostAndPort; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author jaysunxiao + * @version 3.0 + */ +@Ignore +public class UdpServerTest { + + @Test + public void startServerTest() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("server_config.xml"); + var server = new UdpServer(HostAndPort.valueOf(NetContext.getConfigManager().getLocalConfig().getHostConfig().getAddressMap().get("server0"))); + server.start(); + ThreadUtils.sleep(Long.MAX_VALUE); + } + +} diff --git a/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloRequest.java b/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloRequest.java new file mode 100644 index 00000000..24cecb81 --- /dev/null +++ b/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloRequest.java @@ -0,0 +1,40 @@ +/* + * 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.packet.udp; + +import com.zfoo.protocol.IPacket; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpHelloRequest implements IPacket { + + public static final transient short PROTOCOL_ID = 1200; + + private String message; + + + @Override + public short protocolId() { + return PROTOCOL_ID; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloResponse.java b/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloResponse.java new file mode 100644 index 00000000..1386a62a --- /dev/null +++ b/net/src/test/java/com/zfoo/net/packet/udp/UdpHelloResponse.java @@ -0,0 +1,40 @@ +/* + * 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.packet.udp; + +import com.zfoo.protocol.IPacket; + +/** + * @author jaysunxiao + * @version 3.0 + */ +public class UdpHelloResponse implements IPacket { + + public static final transient short PROTOCOL_ID = 1201; + + private String message; + + + @Override + public short protocolId() { + return PROTOCOL_ID; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/net/src/test/resources/protocol.xml b/net/src/test/resources/protocol.xml index 6df92a89..530d969c 100644 --- a/net/src/test/resources/protocol.xml +++ b/net/src/test/resources/protocol.xml @@ -6,7 +6,8 @@ - + + @@ -57,6 +58,9 @@ + + +