前言:这近几天要做一个netty+udp协议做服务端放到腾讯云中,提供给合作公司上传流媒体数据。
1:netty版本
dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.12.Final</version>
</dependency>
下面遇到的几个坑。
1:端口问题。同事帮忙在腾讯云中开方的端口9701,当时没注意看。给我开的端口9701协议是TCP的。导致我测试时在本地一直 ok,部署到云服务器收到不到信息。(这个比较坑)
2:合作公司上传的数据可能有中文(虽然再三确认,没有中文。为了保险还是支持中文)
总结:例子比价简单。我写博客,会把自己遇到的问题也列出来,避免他人入坑。
package park.mecdaemons.bussiness;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.nio.charset.Charset;
import java.util.concurrent.*;
@Service
@Component
@Slf4j
public class UdpEventServer implements ApplicationRunner{
private int port = 9701;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("解析数据开始UdpEventServer..run()");
//开启线程,执行接收处理方法
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("wbAdjust-%d").build();
ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1024), factory, new ThreadPoolExecutor.AbortPolicy());
singleThreadPool.execute(this::doWork);
}
/**
* @return void
* @Author fxk
* @Param []
* @Description : 数据接收线程 方法实现udp上传数据的接收,并将实现数据处理handler
* @Date 2020/10/15 17:00
**/
private void doWork() {
log.info("解析数据开始UdpEventServer..doWork()...1");
try {
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
//由于我们用的是UDP协议,所以要用NioDatagramChannel来创建
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)//支持广播
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//设置处理handler.执行具体处理方法
pipeline.addLast(new updHandler());
}
});
b.bind(port).sync().channel().closeFuture().await();
log.info("解析数据开始UdpEventServer..doWork()...4");
}
catch (InterruptedException e) {
e.printStackTrace();
log.error("执行udp接收服务出错" + e.getMessage());
}
}
}
@Slf4j
public class updHandlerextends SimpleChannelInboundHandler<DatagramPacket> {
private static final Charset CHARSET = Charset.forName("GBK");
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
try {
log.info("ChineseProverbServerHandler..channelRead0()");
//获取消息的ByteBuf
ByteBuf buf = msg.copy().content();
//获取接收到的字节流转为string 这个网上有很多方法,但试了很多,还是这个可以解决中文乱码
String content = (String) buf.readCharSequence(buf.readableBytes(), CHARSET);
log.info("客户端消息111" + "==>" + content);
//通知客户端
//ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("结果:", CharsetUtil.UTF_8), msg.sender()));
//todo 写具体的解析处理方法
} catch (Exception e) {
log.error("类 ChineseProverbServerHandler 出错" + e.getMessage());
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
在云端服务器执行接口