Springboot中用 Netty 開啟UDP服務方式
Netty
Netty是一種提供網絡編程的工具,是對socket編程的一例優(yōu)秀的包裝,支持TCP、UDP、FTP等協議。我們可以用Netty開發(fā)自己的http服務器、udp服務器、FTP服務器,RPC服務器等
Netty大受歡迎的原因:
- 并發(fā)高
Netty支持NIO編程,NIO的持支,可以大大提升并發(fā)性能。
- 傳輸快
Netty NIO的一個特性是零拷貝,直接在內存中開辟一塊,剩去了socket緩沖區(qū),
- 封裝好
接下來寫一個簡單的udp demo。大體思路:
- 寫一個netty的 基于UDP的Server 用來接受數據
- 寫個一處理類,用于對接受的數據進行處理,然后返回信息
新建一個springboot項目。在pom中引入jar
pom.xml
<!--springboot version 我用的是2.1.3.RELEASE-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<!--web模塊的啟動器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- netty依賴 springboot2.x自動導入版本 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<!-- 這里我用到了@slf4j 所以引入這個jar -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
創(chuàng)建NettyUDPServer
Channel 通道的類型
NioSocketChannel, 代表異步的客戶端 TCP Socket 連接.NioServerSocketChannel, 異步的服務器端 TCP Socket 連接.NioDatagramChannel, 異步的 UDP 連接NioSctpChannel, 異步的客戶端 Sctp 連接.NioSctpServerChannel, 異步的 Sctp 服務器端連接.OioSocketChannel, 同步的客戶端 TCP Socket 連接.OioServerSocketChannel, 同步的服務器端 TCP Socket 連接.OioDatagramChannel, 同步的 UDP 連接OioSctpChannel, 同步的 Sctp 服務器端連接.OioSctpServerChannel, 同步的客戶端 TCP Socket 連接.
Bootstrap 是 Netty 提供的一個便利的工廠類,可以通過它來完成 Netty 的客戶端或服務器端的 Netty 初始化。
package com.demo.udpdemo.UDPServer;
import com.demo.udpdemo.handler.BootNettyUdpSimpleChannelInboundHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;
/**
* @author
*/
@Slf4j
public class BootNettyUdpServer {
/**
* 啟動服務
*/
public void bind(int port) {
log.info("-------------------------------udpServer-------------------------");
//表示服務器連接監(jiān)聽線程組,專門接受 accept 新的客戶端client 連接
EventLoopGroup bossLoopGroup = new NioEventLoopGroup();
try {
//1,創(chuàng)建netty bootstrap 啟動類
Bootstrap serverBootstrap = new Bootstrap();
//2、設置boostrap 的eventLoopGroup線程組
serverBootstrap = serverBootstrap.group(bossLoopGroup);
//3、設置NIO UDP連接通道
serverBootstrap = serverBootstrap.channel(NioDatagramChannel.class);
//4、設置通道參數 SO_BROADCAST廣播形式
serverBootstrap = serverBootstrap.option(ChannelOption.SO_BROADCAST, true);
//5、設置處理類 裝配流水線
serverBootstrap = serverBootstrap.handler(new BootNettyUdpSimpleChannelInboundHandler());
//6、綁定server,通過調用sync()方法異步阻塞,直到綁定成功
ChannelFuture f = serverBootstrap.bind(port).sync();
log.info(BootNettyUdpServer.class.getName()+" started and listend on "+f.channel().localAddress());
//7、監(jiān)聽通道關閉事件,應用程序會一直等待,直到channel關閉
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO: handle exception
} finally {
System.out.println("netty udp close!");
//8 關閉EventLoopGroup,
bossLoopGroup.shutdownGracefully();
}
}
}
NettyUdpSimpleChannelInboundHandler
package com.demo.udpdemo.handler;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
/**
* @author
*/
@Slf4j
public class BootNettyUdpSimpleChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
try {
String strdata = msg.content().toString(CharsetUtil.UTF_8);
//打印收到的消息
log.info("---------------------receive data--------------------------");
log.info(strdata);
log.info("---------------------receive data--------------------------");
//收到udp消息后,可通過此方式原路返回的方式返回消息,例如返回時間戳
ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("ok", CharsetUtil.UTF_8), msg.sender()));
} catch (Exception e) {
}
}
}
修改啟動類,啟動執(zhí)行UDPServer.bind方法,啟動udpServer
@SpringBootApplication
@EnableAsync
public class UdpDemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(UdpDemoApplication.class);
app.run(args);
}
@Async
@Override
public void run(String... args){
new BootNettyUdpServer().bind(51000);
}
}
test
在test類下面,新建一個test方法
sendUdpRequestTest
//定義客戶端ip
private static final String SERVER_HOSTNAME = "127.0.0.1";
// 服務器端口
private static final int SERVER_PORT = 51000;
// 本地發(fā)送端口
private static final int LOCAL_PORT = 8888;
@Test
public void sendUdpRequestTest() {
try {
// 1,創(chuàng)建udp服務。通過DatagramSocket對象。
DatagramSocket socket = new DatagramSocket(LOCAL_PORT);
// 2,確定數據,并封裝成數據包。DatagramPacket(byte[] buf, int length, InetAddress
// address, int port)
byte[] buf = "hello".getBytes();
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName(SERVER_HOSTNAME),
SERVER_PORT);
// 3,通過socket服務,將已有的數據包發(fā)送出去。通過send方法。
socket.send(dp);
// 4,關閉資源。
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
結果
2021-09-03 13:14:47.912 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:14:47.912 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : 你好,世界
2021-09-03 13:14:47.912 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:16:11.748 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:16:11.748 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : 你好,世界
2021-09-03 13:16:11.748 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:17:11.664 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:17:11.664 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : hello
2021-09-03 13:17:11.664 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:17:32.714 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
2021-09-03 13:17:32.714 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : hello
2021-09-03 13:17:32.714 INFO 11608 --- [ntLoopGroup-2-1] .BootNettyUdpSimpleChannelInboundHandler : ---------------------receive data--------------------------
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring?Boot實現MyBatis動態(tài)創(chuàng)建表的操作語句
這篇文章主要介紹了Spring?Boot實現MyBatis動態(tài)創(chuàng)建表,MyBatis提供了動態(tài)SQL,我們可以通過動態(tài)SQL,傳入表名等信息然組裝成建表和操作語句,本文通過案例講解展示我們的設計思路,需要的朋友可以參考下2024-01-01
idea集成shell運行環(huán)境以及shell輸出中文亂碼的解決
這篇文章主要介紹了idea集成shell運行環(huán)境以及shell輸出中文亂碼的解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
springboot整合easy-es實現數據的增刪改查的示例代碼
Easy-Es是一款基于ElasticSearch官方提供的RestHighLevelClient打造的低碼開發(fā)框架,本文主要介紹了springboot整合easy-es實現數據的增刪改查的示例代碼,具有一定的參考價值,感興趣的可以了解一下2024-03-03
基于springboot微信公眾號開發(fā)(微信自動回復)
這篇文章主要介紹了基于springboot微信公眾號開發(fā)(微信自動回復),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11
struts2與cookie 實現自動登錄和驗證碼驗證實現代碼
這篇文章主要介紹了struts2與cookie 實現自動登錄和驗證碼驗證實現代碼的相關資料,需要的朋友可以參考下2016-10-10

