feat[udp]: 支持udp服务器

This commit is contained in:
jaysunxiao
2021-07-01 11:19:46 +08:00
parent 7fc4519d4e
commit cdd2579377
24 changed files with 629 additions and 35 deletions
@@ -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();
@@ -37,21 +37,21 @@ public abstract class AbstractServer implements IServer {
private static final Logger logger = LoggerFactory.getLogger(AbstractServer.class);
// 所有的服务器都可以在这个列表中取到
private static final List<AbstractServer> allServers = new ArrayList<>(1);
protected static final List<AbstractServer> 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();
@@ -42,15 +42,15 @@ public class GatewayServer extends AbstractServer {
@Override
public ChannelInitializer<SocketChannel> channelChannelInitializer() {
return new GatewayChannelHandler(packetFilter);
return new ChannelHandlerInitializer(packetFilter);
}
private static class GatewayChannelHandler extends ChannelInitializer<SocketChannel> {
private static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
private BiFunction<Session, IPacket, Boolean> packetFilter;
public GatewayChannelHandler(BiFunction<Session, IPacket, Boolean> packetFilter) {
public ChannelHandlerInitializer(BiFunction<Session, IPacket, Boolean> packetFilter) {
this.packetFilter = packetFilter;
}
@@ -46,15 +46,15 @@ public class WebsocketGatewayServer extends AbstractServer {
@Override
public ChannelInitializer<SocketChannel> channelChannelInitializer() {
return new GatewayChannelHandler(packetFilter);
return new ChannelHandlerInitializer(packetFilter);
}
private static class GatewayChannelHandler extends ChannelInitializer<SocketChannel> {
private static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
private BiFunction<Session, IPacket, Boolean> packetFilter;
public GatewayChannelHandler(BiFunction<Session, IPacket, Boolean> packetFilter) {
public ChannelHandlerInitializer(BiFunction<Session, IPacket, Boolean> packetFilter) {
this.packetFilter = packetFilter;
}
@@ -61,16 +61,16 @@ public class WebsocketSslGatewayServer extends AbstractServer {
@Override
public ChannelInitializer<SocketChannel> channelChannelInitializer() {
return new GatewayChannelHandler(sslContext, packetFilter);
return new ChannelHandlerInitializer(sslContext, packetFilter);
}
private static class GatewayChannelHandler extends ChannelInitializer<SocketChannel> {
private static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
private SslContext sslContext;
private BiFunction<Session, IPacket, Boolean> packetFilter;
public GatewayChannelHandler(SslContext sslContext, BiFunction<Session, IPacket, Boolean> packetFilter) {
public ChannelHandlerInitializer(SslContext sslContext, BiFunction<Session, IPacket, Boolean> packetFilter) {
this.sslContext = sslContext;
this.packetFilter = packetFilter;
}
@@ -35,11 +35,11 @@ public class TcpClient extends AbstractClient {
@Override
public ChannelInitializer<? extends Channel> channelChannelInitializer() {
return new TcpChannelInitHandler();
return new ChannelHandlerInitializer();
}
private static class TcpChannelInitHandler extends ChannelInitializer<SocketChannel> {
private static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) {
channel.pipeline().addLast(new IdleStateHandler(0, 0, 60));
@@ -34,11 +34,11 @@ public class TcpServer extends AbstractServer {
@Override
public ChannelInitializer<SocketChannel> channelChannelInitializer() {
return new TcpChannelHandler();
return new ChannelHandlerInitializer();
}
private static class TcpChannelHandler extends ChannelInitializer<SocketChannel> {
private static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) {
channel.pipeline().addLast(new IdleStateHandler(0, 0, 180));
@@ -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<Channel> channelChannelInitializer() {
return new ChannelHandlerInitializer();
}
private static class ChannelHandlerInitializer extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel channel) {
channel.pipeline().addLast(new UdpCodecHandler());
channel.pipeline().addLast(new ClientDispatcherHandler());
}
}
}
@@ -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<Channel> channelChannelInitializer() {
return new ChannelHandlerInitializer();
}
private static class ChannelHandlerInitializer extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel channel) {
channel.pipeline().addLast(new UdpCodecHandler());
channel.pipeline().addLast(new ServerDispatcherHandler());
}
}
}
@@ -37,11 +37,11 @@ public class WebsocketServer extends AbstractServer {
@Override
public ChannelInitializer<SocketChannel> channelChannelInitializer() {
return new WebSocketServerInitializer();
return new ChannelHandlerInitializer();
}
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel> {
public static class ChannelHandlerInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel channel) {
@@ -59,7 +59,6 @@ public class WebsocketServer extends AbstractServer {
pipeline.addLast(new WebSocketCodecHandler());
pipeline.addLast(new ServerDispatcherHandler());
}
}
}
@@ -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)
@@ -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<DatagramPacket, EncodedPacketInfo> {
private static final Logger logger = LoggerFactory.getLogger(UdpCodecHandler.class);
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket, List<Object> 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<Object> 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;
}
}
}
@@ -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的参数
@@ -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),
;
@@ -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;
}
}
@@ -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;
@@ -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;
@@ -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));
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
}
+5 -1
View File
@@ -6,7 +6,8 @@
<module id="1" name="native" minId="0" maxId="100" version="99.99.999">
<protocol id="0" location="com.zfoo.net.packet.model.SignalPacketAttachment"/>
<protocol id="1" location="com.zfoo.net.packet.model.GatewayPacketAttachment"/>
<protocol id="2" location="com.zfoo.net.packet.model.NoAnswerAttachment"/>
<protocol id="2" location="com.zfoo.net.packet.model.UdpPacketAttachment"/>
<protocol id="3" location="com.zfoo.net.packet.model.NoAnswerAttachment"/>
<protocol id="20" location="com.zfoo.net.core.gateway.model.AuthUidToGatewayCheck"/>
@@ -57,6 +58,9 @@
<protocol id="1165" location="com.zfoo.net.packet.csharp.CM_CSharpRequest" enhance="false"/>
<protocol id="1166" location="com.zfoo.net.packet.csharp.CSharpObjectA" enhance="false"/>
<protocol id="1167" location="com.zfoo.net.packet.csharp.CSharpObjectB" enhance="false"/>
<protocol id="1200" location="com.zfoo.net.packet.udp.UdpHelloRequest"/>
<protocol id="1201" location="com.zfoo.net.packet.udp.UdpHelloResponse"/>
</module>
<module id="4" name="js" minId="2000" maxId="3000" version="1.0.0">