├── .gitignore
├── pom.xml
├── spring-with-netty.iml
└── src
├── main
├── java
│ └── com
│ │ └── moo
│ │ └── springnetty
│ │ ├── cfg
│ │ └── SpringConfig.java
│ │ ├── handlers
│ │ ├── KameProtocolInitalizer.java
│ │ ├── KameServerHandler.java
│ │ ├── ServerHandler.java
│ │ ├── StringProtocolInitalizer.java
│ │ └── codec
│ │ │ └── kame
│ │ │ ├── EncodeType.java
│ │ │ ├── KameRequest.java
│ │ │ ├── KameRequestDecoder.java
│ │ │ ├── KameRequestEncoder.java
│ │ │ ├── KameResponse.java
│ │ │ ├── KameResponseDecoder.java
│ │ │ └── KameResponseEncoder.java
│ │ ├── models
│ │ └── User.java
│ │ └── server
│ │ ├── Main.java
│ │ └── TCPServer.java
└── resources
│ ├── Log4j.properties
│ └── netty-server.properties
└── test
├── java
└── com
│ └── moo
│ └── springnetty
│ ├── server
│ └── TCPServerTest.java
│ └── test
│ ├── TestClient.java
│ ├── TestClientHandler.java
│ └── TestClientInitializer.java
└── resources
├── Log4j.properties
└── netty-server.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | target
3 | Debug.log
4 | Server.log
5 | Server.log.*
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | spring-with-netty
6 | spring-with-netty
7 | 1.0-SNAPSHOT
8 | jar
9 |
10 | spring-with-netty
11 | http://maven.apache.org
12 |
13 |
14 | UTF-8
15 | 4.0.2.RELEASE
16 | 4.0.17.Final
17 | 1.6.1
18 | 4.3.1.Final
19 |
20 |
21 |
22 |
23 | junit
24 | junit
25 | 4.8.1
26 |
27 |
28 | org.springframework
29 | spring-test
30 | ${org.springframework.version}
31 |
32 |
33 |
34 | org.springframework
35 | spring-context
36 | ${org.springframework.version}
37 |
38 |
39 | commons-logging
40 | commons-logging
41 |
42 |
43 |
44 |
45 |
46 | mysql
47 | mysql-connector-java
48 | 5.1.22
49 |
50 |
51 | org.hibernate
52 | hibernate-core
53 | ${org.hibernate.version}
54 |
55 |
56 | org.slf4j
57 | slf4j-api
58 | ${org.slf4j.version}
59 |
60 |
61 | org.slf4j
62 | slf4j-log4j12
63 | ${org.slf4j.version}
64 |
65 |
66 | org.slf4j
67 | jcl-over-slf4j
68 | ${org.slf4j.version}
69 |
70 |
71 | io.netty
72 | netty-all
73 | ${netty.version}
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/spring-with-netty.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/cfg/SpringConfig.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.cfg;
2 |
3 | import com.moo.springnetty.handlers.KameProtocolInitalizer;
4 | import com.moo.springnetty.handlers.StringProtocolInitalizer;
5 | import com.moo.springnetty.handlers.codec.kame.KameRequestDecoder;
6 | import com.moo.springnetty.handlers.codec.kame.KameRequestEncoder;
7 | import com.moo.springnetty.handlers.codec.kame.KameResponseDecoder;
8 | import com.moo.springnetty.handlers.codec.kame.KameResponseEncoder;
9 | import io.netty.bootstrap.ServerBootstrap;
10 | import io.netty.channel.ChannelOption;
11 | import io.netty.channel.nio.NioEventLoopGroup;
12 | import io.netty.channel.socket.nio.NioServerSocketChannel;
13 | import io.netty.handler.codec.string.StringDecoder;
14 | import io.netty.handler.codec.string.StringEncoder;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.beans.factory.annotation.Qualifier;
17 | import org.springframework.beans.factory.annotation.Value;
18 | import org.springframework.context.annotation.Bean;
19 | import org.springframework.context.annotation.ComponentScan;
20 | import org.springframework.context.annotation.Configuration;
21 | import org.springframework.context.annotation.PropertySource;
22 | import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
23 |
24 | import java.net.InetSocketAddress;
25 | import java.util.HashMap;
26 | import java.util.Map;
27 | import java.util.Set;
28 |
29 | @Configuration
30 | @ComponentScan("com.moo")
31 | @PropertySource("classpath:netty-server.properties")
32 | public class SpringConfig {
33 |
34 | @Value("${boss.thread.count}")
35 | private int bossCount;
36 | @Value("${worker.thread.count}")
37 | private int workerCount;
38 | @Value("${tcp.port}")
39 | private int tcpPort;
40 | @Value("${so.keepalive}")
41 | private boolean keepAlive;
42 | @Value("${so.backlog}")
43 | private int backlog;
44 | @Value("${log4j.configuration}")
45 | private String log4jConfiguration;
46 | @Autowired
47 | @Qualifier("springProtocolInitializer")
48 | private StringProtocolInitalizer protocolInitalizer;
49 | @Autowired
50 | @Qualifier("KameProtocolInitalizer")
51 | private KameProtocolInitalizer kameProtocolInitalizer;
52 |
53 | /**
54 | * Necessary to make the Value annotations work.
55 | *
56 | * @return
57 | */
58 | @Bean
59 | public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
60 | return new PropertySourcesPlaceholderConfigurer();
61 | }
62 |
63 | @SuppressWarnings("unchecked")
64 | @Bean(name = "serverBootstrap")
65 | public ServerBootstrap bootstrap() {
66 |
67 | ServerBootstrap b = new ServerBootstrap();
68 | b.group(bossGroup(), workerGroup())
69 | .channel(NioServerSocketChannel.class)
70 | .childHandler(kameProtocolInitalizer);
71 | Map, Object> tcpChannelOptions = tcpChannelOptions();
72 | Set> keySet = tcpChannelOptions.keySet();
73 | for (@SuppressWarnings("rawtypes")
74 | ChannelOption option : keySet) {
75 | b.option(option, tcpChannelOptions.get(option));
76 | }
77 | return b;
78 | }
79 |
80 | @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully")
81 | public NioEventLoopGroup bossGroup() {
82 | return new NioEventLoopGroup(bossCount);
83 | }
84 |
85 | @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully")
86 | public NioEventLoopGroup workerGroup() {
87 | return new NioEventLoopGroup(workerCount);
88 | }
89 |
90 | @Bean(name = "tcpSocketAddress")
91 | public InetSocketAddress tcpPort() {
92 | return new InetSocketAddress(tcpPort);
93 | }
94 |
95 | @Bean(name = "tcpChannelOptions")
96 | public Map, Object> tcpChannelOptions() {
97 | Map, Object> options = new HashMap, Object>();
98 | options.put(ChannelOption.SO_KEEPALIVE, keepAlive);
99 | options.put(ChannelOption.SO_BACKLOG, backlog);
100 | return options;
101 | }
102 |
103 | @Bean(name = "stringEncoder")
104 | public StringEncoder stringEncoder() {
105 | return new StringEncoder();
106 | }
107 |
108 | @Bean(name = "stringDecoder")
109 | public StringDecoder stringDecoder() {
110 | return new StringDecoder();
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/KameProtocolInitalizer.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers;
2 |
3 | import com.moo.springnetty.handlers.codec.kame.KameRequestDecoder;
4 | import com.moo.springnetty.handlers.codec.kame.KameResponseEncoder;
5 | import io.netty.channel.ChannelInitializer;
6 | import io.netty.channel.ChannelPipeline;
7 | import io.netty.channel.socket.SocketChannel;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.factory.annotation.Qualifier;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Component
13 | @Qualifier("KameProtocolInitalizer")
14 | public class KameProtocolInitalizer extends ChannelInitializer {
15 |
16 | @Autowired
17 | private KameServerHandler serverHandler;
18 |
19 | @Override
20 | protected void initChannel(SocketChannel ch) throws Exception {
21 | ChannelPipeline pipeline = ch.pipeline();
22 | pipeline.addLast(new KameRequestDecoder(), serverHandler, new KameResponseEncoder());
23 |
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/KameServerHandler.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers;
2 |
3 | import com.moo.springnetty.handlers.codec.kame.KameRequest;
4 | import com.moo.springnetty.handlers.codec.kame.KameResponse;
5 | import io.netty.channel.*;
6 | import io.netty.channel.ChannelHandler.Sharable;
7 |
8 | import io.netty.util.ReferenceCountUtil;
9 | import org.springframework.beans.factory.annotation.Qualifier;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Component
13 | @Qualifier("serverHandler")
14 | @Sharable
15 | public class KameServerHandler extends ChannelInboundHandlerAdapter {
16 |
17 | @Override
18 | public void channelRead(ChannelHandlerContext ctx, Object msg)
19 | throws Exception {
20 | try {
21 | KameRequest request = (KameRequest) msg;
22 | System.out.println("Server Reciver Data: "+ msg);
23 | KameResponse response = buildResponse();
24 |
25 | // 返回处理结果response
26 | ChannelFuture f = ctx.channel().writeAndFlush(response);
27 | f.addListener(ChannelFutureListener.CLOSE);
28 | } finally {
29 | ReferenceCountUtil.release(msg);
30 | }
31 | }
32 |
33 | @Override
34 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
35 | cause.printStackTrace();
36 | ctx.close();
37 | }
38 |
39 | public KameResponse buildResponse(){
40 | KameResponse response = new KameResponse();
41 | response.setEncode(new Byte("0"));
42 | response.setEncrypt(new Byte("1"));
43 | response.setExtend1(new Byte("1"));
44 | response.setExtend2(new Byte("2"));
45 | response.setResult(4);
46 | response.setSessionId(9);
47 | return response;
48 | }
49 |
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/ServerHandler.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers;
2 |
3 | import io.netty.channel.ChannelHandlerContext;
4 | import io.netty.channel.SimpleChannelInboundHandler;
5 | import io.netty.channel.ChannelHandler.Sharable;
6 |
7 | import org.springframework.beans.factory.annotation.Qualifier;
8 | import org.springframework.stereotype.Component;
9 |
10 | @Component
11 | @Qualifier("serverHandler")
12 | @Sharable
13 | public class ServerHandler extends SimpleChannelInboundHandler {
14 |
15 | @Override
16 | public void channelRead0(ChannelHandlerContext ctx, String msg)
17 | throws Exception {
18 | System.out.print(msg);
19 | ctx.channel().writeAndFlush(msg);
20 | }
21 |
22 | @Override
23 | public void channelActive(ChannelHandlerContext ctx) throws Exception {
24 | System.out.println("Channel is active\n");
25 | super.channelActive(ctx);
26 | }
27 |
28 | @Override
29 | public void channelInactive(ChannelHandlerContext ctx) throws Exception {
30 | System.out.println("\nChannel is disconnected");
31 | super.channelInactive(ctx);
32 | }
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/StringProtocolInitalizer.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers;
2 |
3 | import io.netty.channel.ChannelInitializer;
4 | import io.netty.channel.ChannelPipeline;
5 | import io.netty.channel.socket.SocketChannel;
6 | import io.netty.handler.codec.string.StringDecoder;
7 | import io.netty.handler.codec.string.StringEncoder;
8 |
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.beans.factory.annotation.Qualifier;
11 | import org.springframework.stereotype.Component;
12 |
13 | @Component
14 | @Qualifier("springProtocolInitializer")
15 | public class StringProtocolInitalizer extends ChannelInitializer {
16 |
17 | @Autowired
18 | StringDecoder stringDecoder;
19 |
20 | @Autowired
21 | StringEncoder stringEncoder;
22 |
23 | @Autowired
24 | ServerHandler serverHandler;
25 |
26 | @Override
27 | protected void initChannel(SocketChannel ch) throws Exception {
28 | ChannelPipeline pipeline = ch.pipeline();
29 | pipeline.addLast("decoder", stringDecoder);
30 | pipeline.addLast("handler", serverHandler);
31 | pipeline.addLast("encoder", stringEncoder);
32 | }
33 |
34 | public StringDecoder getStringDecoder() {
35 | return stringDecoder;
36 | }
37 |
38 | public void setStringDecoder(StringDecoder stringDecoder) {
39 | this.stringDecoder = stringDecoder;
40 | }
41 |
42 | public StringEncoder getStringEncoder() {
43 | return stringEncoder;
44 | }
45 |
46 | public void setStringEncoder(StringEncoder stringEncoder) {
47 | this.stringEncoder = stringEncoder;
48 | }
49 |
50 | public ServerHandler getServerHandler() {
51 | return serverHandler;
52 | }
53 |
54 | public void setServerHandler(ServerHandler serverHandler) {
55 | this.serverHandler = serverHandler;
56 | }
57 |
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/codec/kame/EncodeType.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers.codec.kame;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: zheng
6 | * Date: 14-3-4
7 | * Time: 下午9:22
8 | * 0:UTF-8,1:GBK,2:GB2312,3:ISO8859-1
9 | */
10 | public class EncodeType {
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/codec/kame/KameRequest.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers.codec.kame;
2 |
3 | /**
4 | * Kame Request Data
5 | * 协议内容
6 | * 编码方式(1byte)
7 | * 加密(1byte)
8 | * 扩展1(1byte)
9 | * 扩展2(1byte)
10 | * 会话ID(4byte)
11 | * 命令(4byte)
12 | * 包长(4byte)
13 | */
14 | public class KameRequest {
15 |
16 | private byte encode; //编码格式
17 | private byte encrypt; //加密类型
18 | private byte extend1;
19 | private byte extend2;
20 | private int sessionId;
21 | private int command;
22 |
23 |
24 | // 默认构造函数
25 | public KameRequest() {
26 | }
27 |
28 | public KameRequest(int command, int sessionId, byte extend1, byte extend2, byte encrypt, byte encode) {
29 |
30 | this.command = command;
31 | this.sessionId = sessionId;
32 | this.extend2 = extend2;
33 | this.extend1 = extend1;
34 | this.encrypt = encrypt;
35 | this.encode = encode;
36 | }
37 |
38 | public byte getEncode() {
39 | return encode;
40 | }
41 |
42 | public void setEncode(byte encode) {
43 | this.encode = encode;
44 | }
45 |
46 | public byte getEncrypt() {
47 | return encrypt;
48 | }
49 |
50 | public void setEncrypt(byte encrypt) {
51 | this.encrypt = encrypt;
52 | }
53 |
54 | public byte getExtend1() {
55 | return extend1;
56 | }
57 |
58 | public void setExtend1(byte extend1) {
59 | this.extend1 = extend1;
60 | }
61 |
62 | public byte getExtend2() {
63 | return extend2;
64 | }
65 |
66 | public void setExtend2(byte extend2) {
67 | this.extend2 = extend2;
68 | }
69 |
70 | public int getSessionId() {
71 | return sessionId;
72 | }
73 |
74 | public void setSessionId(int sessionId) {
75 | this.sessionId = sessionId;
76 | }
77 |
78 | public int getCommand() {
79 | return command;
80 | }
81 |
82 | public void setCommand(int command) {
83 | this.command = command;
84 | }
85 |
86 | @Override
87 | public String toString() {
88 | return "XLRequest [encode=" + encode + ", encrypt=" + encrypt + ", extend1=" + extend1 + ", extend2=" + extend2
89 | + ", sessionid=" + sessionId + ", command=" + command + "]";
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/com/moo/springnetty/handlers/codec/kame/KameRequestDecoder.java:
--------------------------------------------------------------------------------
1 | package com.moo.springnetty.handlers.codec.kame;
2 |
3 | import io.netty.buffer.ByteBuf;
4 | import io.netty.channel.ChannelHandler;
5 | import io.netty.channel.ChannelHandlerContext;
6 | import io.netty.handler.codec.ByteToMessageDecoder;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * .
12 | * User: zheng
13 | * Date: 14-3-5
14 | * Time: 上午10:03
15 | * 自定义协议解码器
16 | */
17 | public class KameRequestDecoder extends ByteToMessageDecoder {
18 |
19 | @Override
20 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List