`

spring boot 集成原生netty(非netty-io-socket)

 
阅读更多

spring boot 集成netty

先上配置

 

tcp:  
  port: 8090
boss: 
  thread:
    count: 2
worker: 
  thread: 
    count: 2
so: 
  keepalive:  true
  backlog: 100

 很简单的配置,端口开放为8090

 

 

再上配置类:

 

package com.fengbaogu.config;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import com.fengbaogu.handlers.StringProtocolInitalizer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;



@Configuration
public class Config {
	
	@Value("${boss.thread.count}")
	private int bossCount;

	@Value("${worker.thread.count}")
	private int workerCount;

	@Value("${tcp.port}")
	private int tcpPort;

	@Value("${so.keepalive}")
	private boolean keepAlive;

	@Value("${so.backlog}")
	private int backlog;
	
	@Autowired
	@Qualifier("springProtocolInitializer")
	private StringProtocolInitalizer protocolInitalizer;

	@SuppressWarnings("unchecked")
	@Bean(name = "serverBootstrap")
	public ServerBootstrap bootstrap() {
		ServerBootstrap b = new ServerBootstrap();
		b.group(bossGroup(), workerGroup())
				.channel(NioServerSocketChannel.class)
				.childHandler(protocolInitalizer);
		Map<ChannelOption<?>, Object> tcpChannelOptions = tcpChannelOptions();
		Set<ChannelOption<?>> keySet = tcpChannelOptions.keySet();
		for (@SuppressWarnings("rawtypes")
		ChannelOption option : keySet) {
			b.option(option, tcpChannelOptions.get(option));
		}
		return b;
	}

	@Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
	public NioEventLoopGroup bossGroup() {
		return new NioEventLoopGroup(bossCount);
	}

	@Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
	public NioEventLoopGroup workerGroup() {
		return new NioEventLoopGroup(workerCount);
	}

	@Bean(name = "tcpSocketAddress")
	public InetSocketAddress tcpPort() {
		return new InetSocketAddress(tcpPort);
	}

	@Bean(name = "tcpChannelOptions")
	public Map<ChannelOption<?>, Object> tcpChannelOptions() {
		Map<ChannelOption<?>, Object> options = new HashMap<ChannelOption<?>, Object>();
		options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
		options.put(ChannelOption.SO_BACKLOG, backlog);
		return options;
	}

	@Bean(name = "stringEncoder")
	public StringEncoder stringEncoder() {
		return new StringEncoder();
	}

	@Bean(name = "stringDecoder")
	public StringDecoder stringDecoder() {
		return new StringDecoder();
	}

	/**
	 * Necessary to make the Value annotations work.
	 * 
	 * @return
	 */
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}	
}

 其中:

options.put(ChannelOption.SO_KEEPALIVE, keepAlive);

 为保持连接,在服务正常的情况下,不主动关闭连接,连接是不会断的。

 

基本配置已经OK,现在配置字符串的协议:

package com.fengbaogu.handlers;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * Just a dummy protocol mainly to show the ServerBootstrap being initialized.
 * 
 * @author Abraham Menacherry
 * 
 */
@Component
@Qualifier("springProtocolInitializer")
public class StringProtocolInitalizer extends ChannelInitializer<SocketChannel> {

	@Autowired
	StringDecoder stringDecoder;

	@Autowired
	StringEncoder stringEncoder;

	@Autowired
	ServerHandler serverHandler;

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();
		pipeline.addLast("decoder", stringDecoder);
		pipeline.addLast("handler", serverHandler);
		pipeline.addLast("encoder", stringEncoder);
	}

	public StringDecoder getStringDecoder() {
		return stringDecoder;
	}

	public void setStringDecoder(StringDecoder stringDecoder) {
		this.stringDecoder = stringDecoder;
	}

	public StringEncoder getStringEncoder() {
		return stringEncoder;
	}

	public void setStringEncoder(StringEncoder stringEncoder) {
		this.stringEncoder = stringEncoder;
	}

	public ServerHandler getServerHandler() {
		return serverHandler;
	}

	public void setServerHandler(ServerHandler serverHandler) {
		this.serverHandler = serverHandler;
	}

}

 此配置,可直接解码字符串数据,及自己的处理器逻辑

 现在我们来上自己的处理器逻辑:

 

package com.fengbaogu.handlers;

import java.net.InetAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

@Component
@Qualifier("serverHandler")
@Sharable
public class ServerHandler extends SimpleChannelInboundHandler<String> {

	private static final Logger log = LoggerFactory.getLogger(ServerHandler.class);
	
	@Override
	public void channelRead0(ChannelHandlerContext ctx, String msg)
			throws Exception {
		log.info("client msg:"+msg);
		String clientIdToLong= ctx.channel().id().asLongText();
		log.info("client long id:"+clientIdToLong);
		String clientIdToShort= ctx.channel().id().asShortText();
		log.info("client short id:"+clientIdToShort);
		if(msg.indexOf("bye")!=-1){
			//close
			ctx.channel().close();
		}else{
			//send to client 
			ctx.channel().writeAndFlush("Yoru msg is:"+msg);
			
		}
		
	}
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		
		
		
		
		log.info("RamoteAddress : " + ctx.channel().remoteAddress() + " active !");
        
        ctx.channel().writeAndFlush( "Welcome to " + InetAddress.getLocalHost().getHostName() + " service!\n");
        
		super.channelActive(ctx);
	}
	

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		log.info("\nChannel is disconnected");
		super.channelInactive(ctx);
	}

	
	
	
}

 逻辑和简单的业务已经实现。现在我们来配置netty的启动类。

 

package com.fengbaogu.config;

import java.net.InetSocketAddress;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
@Component
public class TCPServer {
	@Autowired
	@Qualifier("serverBootstrap")
	private ServerBootstrap b;
	
	@Autowired
	@Qualifier("tcpSocketAddress")
	private InetSocketAddress tcpPort;

	private ChannelFuture serverChannelFuture;

	@PostConstruct
	public void start() throws Exception {
		System.out.println("Starting server at " + tcpPort);
		serverChannelFuture = b.bind(tcpPort).sync();
	}

	@PreDestroy
	public void stop() throws Exception {
	    serverChannelFuture.channel().closeFuture().sync();
	}

	public ServerBootstrap getB() {
		return b;
	}

	public void setB(ServerBootstrap b) {
		this.b = b;
	}

	public InetSocketAddress getTcpPort() {
		return tcpPort;
	}

	public void setTcpPort(InetSocketAddress tcpPort) {
		this.tcpPort = tcpPort;
	}
}

 

利用@PostConstruct和@PreDestroy来开启和关闭netty

启动boot,利用telnet连接,我们来看效果

telnet 192.168.1.44 8090

 显示:

Connecting to 192.168.1.44:8090...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Welcome to DESKTOP-QOTQUO6 service!

 说明已经连接上了

 各项测试通过,spring boot集成netty

 下面上传源代码,其中netty的jar包请到官方下载,我是自己上传的自己的私服

 

 

 

分享到:
评论
1 楼 linkai098 2017-12-07  
谢谢大神啦

相关推荐

    springboot netty-socket-io免费聊天系统

    springboot netty-sockeit-io免费聊天系统,支持一对一,一对多,单独聊,私聊,群聊,开箱即用,支持图片、文件发送接收,支持windows、linux,支持pc端、手机端,支持ie8、firefox、chrome任意浏览器 自己安装...

    spring-boot-starter-reactor-netty-2.1.6.RELEASE.jar

    java运行依赖jar包

    netty-spring-boot-starter:Netty与Spring Boot集成

    netty-spring-boot-starter 基于Netty的Spring Boot Starter工程。 介绍 支持TCP长连接消息转发到Spring容器 支持自定义消息枚举类( CommandController , CommandMapping ) 支持自定义通信协议解析( ...

    netty-transport-native-unix-common-4.1.73.Final-API文档-中英对照版.zip

    Maven坐标:io.netty:netty-transport-native-unix-common:4.1.73.Final; 标签:common、native、transport、unix、netty、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器

    netty-codec-mqtt-4.1.73.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-codec-mqtt:4.1.73.Final; 标签:codec、mqtt、netty、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档...

    transport-netty4-client-5.5.1-API文档-中英对照版.zip

    赠送jar包:transport-netty4-client-5.5.1.jar; 赠送原API文档:transport-netty4-client-5.5.1-javadoc.jar; 赠送源代码:transport-netty4-client-5.5.1-sources.jar; 赠送Maven依赖信息文件:transport-netty...

    netty-resolver-dns-4.1.73.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-resolver-dns:4.1.73.Final; 标签:resolver、dns、netty、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...

    spring boot 整合的netty 实现的socket的服务端和客户端

    整合Spring Boot与Netty,可以利用Spring的便捷性和Netty的高效性来构建实时通信系统,例如基于Socket的服务。以下将详细讲解如何实现Spring Boot整合Netty的Socket服务端和客户端。 首先,我们来看服务端的实现。...

    netty-transport-native-unix-common-4.1.74.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-transport-native-unix-common:4.1.74.Final; 标签:netty、transport、native、unix、common、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index

    netty-transport-native-unix-common-4.1.68.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-transport-native-unix-common:4.1.68.Final; 标签:netty、transport、native、unix、common、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index

    netty-transport-classes-epoll-4.1.73.Final-API文档-中英对照版.zip

    Maven坐标:io.netty:netty-transport-classes-epoll:4.1.73.Final; 标签:classes、epoll、transport、netty、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可...

    netty-transport-classes-epoll-4.1.73.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-transport-classes-epoll:4.1.73.Final; 标签:classes、epoll、transport、netty、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览...

    netty-resolver-dns-4.1.65.Final-API文档-中英对照版.zip

    Maven坐标:io.netty:netty-resolver-dns:4.1.65.Final; 标签:netty、resolver、dns、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...

    netty-transport-classes-epoll-4.1.74.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-transport-classes-epoll:4.1.74.Final; 标签:netty、transport、classes、epoll、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览...

    boot-example-netty-tcp-2.0.5

    使用SpringBoot2.x集成Netty4.x创建基于TCP/IP协议的服务端和客户端的Demo代码案例 使用了SpringBoot+swaggerUI方式进行测试,客户端可以给服务端发送消息,服务端也可以给已经连上的客户端发送消息,使用了通道保活...

    netty-socketio-netty-socketio-2.0.6

    netty-socketio-netty-socketio-2.0.6 ,Socket.IO 是一个库,可以在客户端和服务器之间实现低延迟, 双向和基于事件的通信:netty-socketio-netty-socketio-2.0.6.tar.gznetty-socketio-netty-socketio-2.0.6.zip

    netty-codec-dns-4.1.65.Final-API文档-中英对照版.zip

    Maven坐标:io.netty:netty-codec-dns:4.1.65.Final; 标签:netty、codec、dns、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...

    netty-resolver-dns-4.1.65.Final-API文档-中文版.zip

    Maven坐标:io.netty:netty-resolver-dns:4.1.65.Final; 标签:netty、resolver、dns、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...

    netty+spring服务端-omen-1.1

    omen-1.1 自己基于netty开发的服务端,支持spring配置服务器启动模式:http,tcp,websocket等,并支持NIO和OIO方式,项目已应用于生产,可以通过jar形式加入其它项目,业务类实现业务service,启动不依赖于其他应用...

Global site tag (gtag.js) - Google Analytics