├── netty-common ├── src │ └── main │ │ └── java │ │ └── com │ │ └── haoxy │ │ └── common │ │ ├── ivm │ │ └── model │ │ └── CustomProtocol.java ├── target │ └── classes │ │ └── com │ │ └── haoxy │ │ └── common │ │ └── model │ │ └── CustomProtocol.class ├── pom.xml └── netty-common.iml ├── netty-server ├── src │ └── main │ │ ├── resources │ │ └── application.properties │ │ └── java │ │ └── com │ │ └── haoxy │ │ └── server │ │ ├── ServerApp.java │ │ ├── init │ │ └── HeartbeatInitializer.java │ │ ├── util │ │ └── NettySocketHolder.java │ │ ├── encode │ │ └── HeartbeatDecoder.java │ │ ├── handle │ │ └── HeartBeatSimpleHandle.java │ │ └── heart │ │ └── HeartBeatServer.java ├── target │ └── classes │ │ ├── application.properties │ │ └── com │ │ └── haoxy │ │ └── server │ │ ├── ServerApp.class │ │ ├── heart │ │ └── HeartBeatServer.class │ │ ├── encode │ │ └── HeartbeatDecoder.class │ │ ├── util │ │ └── NettySocketHolder.class │ │ ├── init │ │ └── HeartbeatInitializer.class │ │ └── handle │ │ └── HeartBeatSimpleHandle.class ├── pom.xml └── netty-server.iml ├── netty-client ├── target │ └── classes │ │ ├── com │ │ └── haoxy │ │ │ └── client │ │ │ ├── ClientApp.class │ │ │ ├── heart │ │ │ └── HeartbeatClient.class │ │ │ ├── config │ │ │ └── HeartBeatConfig.class │ │ │ ├── encode │ │ │ └── HeartbeatEncode.class │ │ │ ├── handle │ │ │ └── EchoClientHandle.class │ │ │ ├── util │ │ │ └── SpringBeanFactory.class │ │ │ └── init │ │ │ └── CustomerHandleInitializer.class │ │ └── application.properties ├── src │ └── main │ │ ├── resources │ │ └── application.properties │ │ └── java │ │ └── com │ │ └── haoxy │ │ └── client │ │ ├── ClientApp.java │ │ ├── config │ │ └── HeartBeatConfig.java │ │ ├── encode │ │ └── HeartbeatEncode.java │ │ ├── init │ │ └── CustomerHandleInitializer.java │ │ ├── util │ │ └── SpringBeanFactory.java │ │ ├── heart │ │ └── HeartbeatClient.java │ │ └── handle │ │ └── EchoClientHandle.java ├── pom.xml └── netty-client.iml ├── .idea ├── kotlinc.xml ├── misc.xml ├── encodings.xml ├── libraries │ ├── Maven__junit_junit_4_11.xml │ ├── Maven__org_ow2_asm_asm_5_0_3.xml │ ├── Maven__org_yaml_snakeyaml_1_17.xml │ ├── Maven__org_objenesis_objenesis_2_1.xml │ ├── Maven__org_slf4j_slf4j_api_1_7_25.xml │ ├── Maven__com_fasterxml_classmate_1_3_3.xml │ ├── Maven__net_minidev_json_smart_2_2_1.xml │ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml │ ├── Maven__org_assertj_assertj_core_2_6_0.xml │ ├── Maven__org_slf4j_jul_to_slf4j_1_7_25.xml │ ├── Maven__org_skyscreamer_jsonassert_1_4_0.xml │ ├── Maven__net_minidev_accessors_smart_1_1.xml │ ├── Maven__com_jayway_jsonpath_json_path_2_2_0.xml │ ├── Maven__io_netty_netty_all_4_1_21_Final.xml │ ├── Maven__org_mockito_mockito_core_1_10_19.xml │ ├── Maven__org_slf4j_jcl_over_slf4j_1_7_25.xml │ ├── Maven__org_hamcrest_hamcrest_library_1_3.xml │ ├── Maven__ch_qos_logback_logback_core_1_1_11.xml │ ├── Maven__org_slf4j_log4j_over_slf4j_1_7_25.xml │ ├── Maven__ch_qos_logback_logback_classic_1_1_11.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_8_9.xml │ ├── Maven__org_jboss_logging_jboss_logging_3_3_1_Final.xml │ ├── Maven__javax_validation_validation_api_1_1_0_Final.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_16.xml │ ├── Maven__org_springframework_spring_aop_4_3_10_RELEASE.xml │ ├── Maven__org_springframework_spring_web_4_3_10_RELEASE.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_8_9.xml │ ├── Maven__org_springframework_spring_core_4_3_10_RELEASE.xml │ ├── Maven__org_springframework_spring_test_4_3_10_RELEASE.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_16.xml │ ├── Maven__org_springframework_spring_beans_4_3_10_RELEASE.xml │ ├── Maven__org_hibernate_hibernate_validator_5_3_5_Final.xml │ ├── Maven__org_springframework_boot_spring_boot_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_spring_webmvc_4_3_10_RELEASE.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml │ ├── Maven__org_springframework_spring_context_4_3_10_RELEASE.xml │ ├── Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_16.xml │ ├── Maven__org_springframework_spring_expression_4_3_10_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_test_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_1_5_6_RELEASE.xml │ ├── Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_web_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_test_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_tomcat_1_5_6_RELEASE.xml │ ├── Maven__org_springframework_boot_spring_boot_starter_logging_1_5_6_RELEASE.xml │ └── Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_5_6_RELEASE.xml ├── modules.xml ├── compiler.xml ├── inspectionProfiles │ └── Project_Default.xml └── workspace.xml ├── .gitignore ├── springboot-netty.iml ├── pom.xml └── README.md /netty-common/src/main/java/com/haoxy/common/ivm: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /netty-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # web port 2 | server.port=8081 3 | netty.server.port=11211 4 | 5 | 6 | -------------------------------------------------------------------------------- /netty-server/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | # web port 2 | server.port=8081 3 | netty.server.port=11211 4 | 5 | 6 | -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/ClientApp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/ClientApp.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/ServerApp.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/ServerApp.class -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/heart/HeartbeatClient.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/heart/HeartbeatClient.class -------------------------------------------------------------------------------- /netty-common/target/classes/com/haoxy/common/model/CustomProtocol.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-common/target/classes/com/haoxy/common/model/CustomProtocol.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/heart/HeartBeatServer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/heart/HeartBeatServer.class -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /netty-client/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # web port 2 | server.port=8082 3 | # 通道 ID 4 | channel.id=100 5 | 6 | netty.server.host=127.0.0.1 7 | netty.server.port=11211 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /netty-client/target/classes/application.properties: -------------------------------------------------------------------------------- 1 | # web port 2 | server.port=8082 3 | # 通道 ID 4 | channel.id=100 5 | 6 | netty.server.host=127.0.0.1 7 | netty.server.port=11211 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/config/HeartBeatConfig.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/config/HeartBeatConfig.class -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/encode/HeartbeatEncode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/encode/HeartbeatEncode.class -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/handle/EchoClientHandle.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/handle/EchoClientHandle.class -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/util/SpringBeanFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/util/SpringBeanFactory.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/encode/HeartbeatDecoder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/encode/HeartbeatDecoder.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/util/NettySocketHolder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/util/NettySocketHolder.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/init/HeartbeatInitializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/init/HeartbeatInitializer.class -------------------------------------------------------------------------------- /netty-server/target/classes/com/haoxy/server/handle/HeartBeatSimpleHandle.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-server/target/classes/com/haoxy/server/handle/HeartBeatSimpleHandle.class -------------------------------------------------------------------------------- /netty-client/target/classes/com/haoxy/client/init/CustomerHandleInitializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haoxiaoyong1014/springboot-netty/HEAD/netty-client/target/classes/com/haoxy/client/init/CustomerHandleInitializer.class -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__junit_junit_4_11.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/ClientApp.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Created by haoxy on 2018/10/17. 8 | * E-mail:hxyHelloWorld@163.com 9 | * github:https://github.com/haoxiaoyong1014 10 | */ 11 | @SpringBootApplication 12 | public class ClientApp { 13 | public static void main(String[] args) { 14 | SpringApplication.run(ClientApp.class,args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/ServerApp.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Created by haoxy on 2018/10/17. 8 | * E-mail:hxyHelloWorld@163.com 9 | * github:https://github.com/haoxiaoyong1014 10 | */ 11 | @SpringBootApplication 12 | public class ServerApp { 13 | public static void main(String[] args) { 14 | SpringApplication.run(ServerApp.class,args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_ow2_asm_asm_5_0_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_yaml_snakeyaml_1_17.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /netty-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-netty 7 | com.haoxy.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-common 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_objenesis_objenesis_2_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_25.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_classmate_1_3_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_minidev_json_smart_2_2_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_assertj_assertj_core_2_6_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_25.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_skyscreamer_jsonassert_1_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__net_minidev_accessors_smart_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_netty_netty_all_4_1_21_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mockito_mockito_core_1_10_19.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_25.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_library_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_core_1_1_11.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_log4j_over_slf4j_1_7_25.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__ch_qos_logback_logback_classic_1_1_11.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_8_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_jboss_logging_jboss_logging_3_3_1_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__javax_validation_validation_api_1_1_0_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_el_8_5_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_aop_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_web_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_8_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_core_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_test_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_8_5_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_beans_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hibernate_hibernate_validator_5_3_5_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_webmvc_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_8_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_context_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/config/HeartBeatConfig.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.config; 2 | 3 | import com.haoxy.common.model.CustomProtocol; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | /** 9 | * Created by haoxy on 2018/10/17. 10 | * E-mail:hxyHelloWorld@163.com 11 | * github:https://github.com/haoxiaoyong1014 12 | */ 13 | @Configuration 14 | public class HeartBeatConfig { 15 | 16 | @Value("${channel.id}") 17 | private long id; 18 | 19 | @Bean(value = "heartBeat") 20 | public CustomProtocol heartBeat(){ 21 | return new CustomProtocol(id,"ping") ; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_8_5_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_expression_4_3_10_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_test_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/encode/HeartbeatEncode.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.encode; 2 | 3 | import com.haoxy.common.model.CustomProtocol; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToByteEncoder; 7 | 8 | /** 9 | * Created by haoxy on 2018/10/17. 10 | * E-mail:hxyHelloWorld@163.com 11 | * github:https://github.com/haoxiaoyong1014 12 | * 客户端编码器 13 | */ 14 | public class HeartbeatEncode extends MessageToByteEncoder { 15 | @Override 16 | protected void encode(ChannelHandlerContext channelHandlerContext, CustomProtocol customProtocol, ByteBuf byteBuf) throws Exception { 17 | byteBuf.writeLong(customProtocol.getId()) ; 18 | byteBuf.writeBytes(customProtocol.getContent().getBytes()) ; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_1_5_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/init/CustomerHandleInitializer.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.init; 2 | 3 | import com.haoxy.client.encode.HeartbeatEncode; 4 | import com.haoxy.client.handle.EchoClientHandle; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelInitializer; 7 | import io.netty.handler.timeout.IdleStateHandler; 8 | 9 | /** 10 | * Created by haoxy on 2018/10/17. 11 | * E-mail:hxyHelloWorld@163.com 12 | * github:https://github.com/haoxiaoyong1014 13 | */ 14 | public class CustomerHandleInitializer extends ChannelInitializer { 15 | @Override 16 | protected void initChannel(Channel channel) throws Exception { 17 | channel.pipeline() 18 | //10 秒没发送消息 将IdleStateHandler 添加到 ChannelPipeline 中 19 | .addLast(new IdleStateHandler(0, 10, 0)) 20 | .addLast(new HeartbeatEncode()) 21 | .addLast(new EchoClientHandle()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/init/HeartbeatInitializer.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server.init; 2 | 3 | import com.haoxy.server.encode.HeartbeatDecoder; 4 | import com.haoxy.server.handle.HeartBeatSimpleHandle; 5 | import io.netty.channel.Channel; 6 | import io.netty.channel.ChannelInitializer; 7 | import io.netty.handler.timeout.IdleStateHandler; 8 | 9 | /** 10 | * Created by haoxy on 2018/10/17. 11 | * E-mail:hxyHelloWorld@163.com 12 | * github:https://github.com/haoxiaoyong1014 13 | */ 14 | public class HeartbeatInitializer extends ChannelInitializer { 15 | @Override 16 | protected void initChannel(Channel channel) throws Exception { 17 | channel.pipeline() 18 | //五秒没有收到消息 将IdleStateHandler 添加到 ChannelPipeline 中 19 | .addLast(new IdleStateHandler(5, 0, 0)) 20 | .addLast(new HeartbeatDecoder()) 21 | .addLast(new HeartBeatSimpleHandle()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/util/SpringBeanFactory.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by haoxy on 2018/10/17. 10 | * E-mail:hxyHelloWorld@163.com 11 | * github:https://github.com/haoxiaoyong1014 12 | */ 13 | @Component 14 | public final class SpringBeanFactory implements ApplicationContextAware { 15 | 16 | private static ApplicationContext context; 17 | 18 | public static T getBean(Class c){ 19 | return context.getBean(c); 20 | } 21 | 22 | 23 | public static T getBean(String name,Class clazz){ 24 | return context.getBean(name,clazz); 25 | } 26 | 27 | @Override 28 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 29 | context = applicationContext; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/util/NettySocketHolder.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server.util; 2 | 3 | import io.netty.channel.socket.nio.NioSocketChannel; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | /** 9 | * Created by haoxy on 2018/10/17. 10 | * E-mail:hxyHelloWorld@163.com 11 | * github:https://github.com/haoxiaoyong1014 12 | */ 13 | public class NettySocketHolder { 14 | 15 | private static final Map MAP = new ConcurrentHashMap<>(16); 16 | 17 | public static void put(Long id, NioSocketChannel socketChannel) { 18 | MAP.put(id, socketChannel); 19 | } 20 | 21 | public static NioSocketChannel get(Long id) { 22 | return MAP.get(id); 23 | } 24 | 25 | public static Map getMAP() { 26 | return MAP; 27 | } 28 | 29 | public static void remove(NioSocketChannel nioSocketChannel) { 30 | MAP.entrySet().stream().filter(entry -> entry.getValue() == nioSocketChannel).forEach(entry -> MAP.remove(entry.getKey())); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/encode/HeartbeatDecoder.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server.encode; 2 | 3 | import com.haoxy.common.model.CustomProtocol; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ByteToMessageDecoder; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by haoxy on 2018/10/17. 12 | * E-mail:hxyHelloWorld@163.com 13 | * github:https://github.com/haoxiaoyong1014 14 | * 服务端解码器 15 | */ 16 | public class HeartbeatDecoder extends ByteToMessageDecoder { 17 | @Override 18 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { 19 | long id = byteBuf.readLong(); 20 | byte[] bytes = new byte[byteBuf.readableBytes()]; 21 | byteBuf.readBytes(bytes); 22 | String content = new String(bytes); 23 | CustomProtocol customProtocol = new CustomProtocol(); 24 | customProtocol.setId(id); 25 | customProtocol.setContent(content); 26 | list.add(customProtocol); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lt application files and Maven 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | 12 | # Compiled class files 13 | *.class 14 | 15 | # Log Files 16 | *.log 17 | 18 | # About IntelliJ 19 | *.iml 20 | /.idea/ 21 | /out/ 22 | 23 | # BlueJ files 24 | *.ctxt 25 | 26 | # Mobile Tools for Java (J2ME) 27 | .mtj.tmp/ 28 | 29 | # macOS 30 | .DS_Store 31 | 32 | # Package Files 33 | *.jar 34 | *.war 35 | *.ear 36 | *.zip 37 | *.tar.gz 38 | *.rar 39 | 40 | # CMake 41 | cmake-build-debug/ 42 | 43 | # File-based project format 44 | *.iws 45 | 46 | # mpeltonen/sbt-idea plugin 47 | .idea_modules/ 48 | 49 | # JIRA plugin 50 | atlassian-ide-plugin.xml 51 | 52 | # Crashlytics plugin (for Android Studio and IntelliJ) 53 | com_crashlytics_export_strings.xml 54 | crashlytics.properties 55 | crashlytics-build.properties 56 | fabric.properties 57 | 58 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 59 | hs_err_pid* 60 | 61 | -------------------------------------------------------------------------------- /springboot-netty.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /netty-common/netty-common.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | -------------------------------------------------------------------------------- /netty-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-netty 7 | com.haoxy.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-client 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-test 21 | test 22 | 23 | 24 | com.haoxy.netty 25 | netty-common 26 | 1.0-SNAPSHOT 27 | 28 | 29 | -------------------------------------------------------------------------------- /netty-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | springboot-netty 7 | com.haoxy.netty 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | netty-server 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-test 22 | test 23 | 24 | 25 | com.haoxy.netty 26 | netty-common 27 | 1.0-SNAPSHOT 28 | 29 | 30 | -------------------------------------------------------------------------------- /netty-common/src/main/java/com/haoxy/common/model/CustomProtocol.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.common.model; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by haoxy on 2018/10/17. 7 | * E-mail:hxyHelloWorld@163.com 8 | * github:https://github.com/haoxiaoyong1014 9 | */ 10 | public class CustomProtocol implements Serializable { 11 | 12 | 13 | private static final long serialVersionUID = 290429819350651974L; 14 | private long id; 15 | private String content; 16 | 17 | public long getId() { 18 | return id; 19 | } 20 | 21 | public void setId(long id) { 22 | this.id = id; 23 | } 24 | 25 | public String getContent() { 26 | return content; 27 | } 28 | 29 | public void setContent(String content) { 30 | this.content = content; 31 | } 32 | 33 | public CustomProtocol(long id, String content) { 34 | this.id = id; 35 | this.content = content; 36 | } 37 | public CustomProtocol(){ 38 | 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "CustomProtocol{" + 44 | "id=" + id + 45 | ", content='" + content + '\'' + 46 | '}'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 1.5.6.RELEASE 10 | 11 | 12 | com.haoxy.netty 13 | springboot-netty 14 | pom 15 | 1.0-SNAPSHOT 16 | 17 | netty-client 18 | netty-server 19 | netty-common 20 | 21 | 22 | 4.11 23 | 4.1.21.Final 24 | UTF-8 25 | UTF-8 26 | 27 | 28 | 29 | 30 | io.netty 31 | netty-all 32 | ${netty.version} 33 | 34 | 35 | 36 | junit 37 | junit 38 | ${junit.version} 39 | 40 | 41 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/heart/HeartbeatClient.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.heart; 2 | 3 | import com.haoxy.client.init.CustomerHandleInitializer; 4 | import io.netty.bootstrap.Bootstrap; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.EventLoopGroup; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.nio.NioSocketChannel; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.annotation.PostConstruct; 15 | import io.netty.channel.socket.SocketChannel; 16 | 17 | /** 18 | * Created by haoxy on 2018/10/17. 19 | * E-mail:hxyHelloWorld@163.com 20 | * github:https://github.com/haoxiaoyong1014 21 | */ 22 | @Component 23 | public class HeartbeatClient { 24 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartbeatClient.class); 25 | private EventLoopGroup group = new NioEventLoopGroup(); 26 | @Value("${netty.server.port}") 27 | private int nettyPort; 28 | @Value("${netty.server.host}") 29 | private String host; 30 | 31 | private SocketChannel socketChannel; 32 | 33 | @PostConstruct 34 | public void start() throws InterruptedException { 35 | Bootstrap bootstrap = new Bootstrap(); 36 | /** 37 | * NioSocketChannel用于创建客户端通道,而不是NioServerSocketChannel。 38 | * 请注意,我们不像在ServerBootstrap中那样使用childOption(),因为客户端SocketChannel没有父服务器。 39 | */ 40 | bootstrap.group(group).channel(NioSocketChannel.class).handler(new CustomerHandleInitializer()); 41 | /** 42 | * 启动客户端 43 | * 我们应该调用connect()方法而不是bind()方法。 44 | */ 45 | ChannelFuture future = bootstrap.connect(host, nettyPort).sync(); 46 | if (future.isSuccess()) { 47 | LOGGER.info("启动 Netty 成功"); 48 | } 49 | 50 | socketChannel = (SocketChannel) future.channel(); 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /netty-client/src/main/java/com/haoxy/client/handle/EchoClientHandle.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.client.handle; 2 | 3 | import com.haoxy.client.util.SpringBeanFactory; 4 | import com.haoxy.common.model.CustomProtocol; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.channel.ChannelFutureListener; 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.SimpleChannelInboundHandler; 9 | import io.netty.handler.timeout.IdleState; 10 | import io.netty.handler.timeout.IdleStateEvent; 11 | import io.netty.util.CharsetUtil; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | /** 16 | * Created by haoxy on 2018/10/17. 17 | * E-mail:hxyHelloWorld@163.com 18 | * github:https://github.com/haoxiaoyong1014 19 | * 20 | * EchoClientHandle继承了 ChannelInboundHandlerAdapter 的一个扩展(SimpleChannelInboundHandler), 21 | * 而ChannelInboundHandlerAdapter是ChannelInboundHandler的一个实现 22 | * ChannelInboundHandler提供了可以重写的各种事件处理程序方法 23 | * 目前,只需继承 SimpleChannelInboundHandler或ChannelInboundHandlerAdapter 而不是自己实现处理程序接口。 24 | * 我们在这里重写了channelRead0()事件处理程序方法 25 | */ 26 | public class EchoClientHandle extends SimpleChannelInboundHandler { 27 | 28 | private final static Logger LOGGER = LoggerFactory.getLogger(EchoClientHandle.class); 29 | 30 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 31 | if (evt instanceof IdleStateEvent) { 32 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt; 33 | if (idleStateEvent.state() == IdleState.WRITER_IDLE) { 34 | LOGGER.info("已经10秒没收到消息了"); 35 | //向服务端发送消息 36 | CustomProtocol heartBeat = SpringBeanFactory.getBean("heartBeat",CustomProtocol.class); 37 | ctx.writeAndFlush(heartBeat).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); 38 | } 39 | 40 | } 41 | super.userEventTriggered(ctx, evt); 42 | } 43 | 44 | /** 45 | * 每当从服务端接收到新数据时,都会使用收到的消息调用此方法 channelRead0(),在此示例中,接收消息的类型是ByteBuf。 46 | * @param channelHandlerContext 47 | * @param byteBuf 48 | * @throws Exception 49 | */ 50 | @Override 51 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { 52 | //从服务端收到消息时被调用 53 | LOGGER.info("客户端收到消息={}", byteBuf.toString(CharsetUtil.UTF_8)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/handle/HeartBeatSimpleHandle.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server.handle; 2 | 3 | import com.haoxy.common.model.CustomProtocol; 4 | import com.haoxy.server.util.NettySocketHolder; 5 | import io.netty.buffer.ByteBuf; 6 | import io.netty.buffer.Unpooled; 7 | import io.netty.channel.ChannelFuture; 8 | import io.netty.channel.ChannelFutureListener; 9 | import io.netty.channel.ChannelHandlerContext; 10 | import io.netty.channel.SimpleChannelInboundHandler; 11 | import io.netty.channel.socket.nio.NioSocketChannel; 12 | import io.netty.handler.timeout.IdleState; 13 | import io.netty.handler.timeout.IdleStateEvent; 14 | import io.netty.util.CharsetUtil; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | /** 19 | * Created by haoxy on 2018/10/17. 20 | * E-mail:hxyHelloWorld@163.com 21 | * github:https://github.com/haoxiaoyong1014 22 | */ 23 | public class HeartBeatSimpleHandle extends SimpleChannelInboundHandler { 24 | 25 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartBeatSimpleHandle.class); 26 | private static final ByteBuf HEART_BEAT = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer(new CustomProtocol(123456L, "pong").toString(), CharsetUtil.UTF_8)); 27 | 28 | /** 29 | * 取消绑定 30 | * @param ctx 31 | * @throws Exception 32 | */ 33 | @Override 34 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 35 | NettySocketHolder.remove((NioSocketChannel) ctx.channel()); 36 | } 37 | 38 | @Override 39 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 40 | if (evt instanceof IdleStateEvent) { 41 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt; 42 | if (idleStateEvent.state() == IdleState.READER_IDLE) { 43 | LOGGER.info("已经5秒没有收到信息!"); 44 | //向客户端发送消息 45 | ctx.writeAndFlush(HEART_BEAT).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); 46 | } 47 | } 48 | super.userEventTriggered(ctx, evt); 49 | } 50 | 51 | @Override 52 | protected void channelRead0(ChannelHandlerContext ctx, CustomProtocol customProtocol) throws Exception { 53 | LOGGER.info("收到customProtocol={}", customProtocol); 54 | //我们调用writeAndFlush(Object)来逐字写入接收到的消息并刷新线路 55 | //ctx.writeAndFlush(customProtocol); 56 | //保存客户端与 Channel 之间的关系 57 | NettySocketHolder.put(customProtocol.getId(), (NioSocketChannel) ctx.channel()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /netty-server/src/main/java/com/haoxy/server/heart/HeartBeatServer.java: -------------------------------------------------------------------------------- 1 | package com.haoxy.server.heart; 2 | 3 | import com.haoxy.server.init.HeartbeatInitializer; 4 | import io.netty.bootstrap.ServerBootstrap; 5 | import io.netty.channel.ChannelFuture; 6 | import io.netty.channel.ChannelOption; 7 | import io.netty.channel.EventLoopGroup; 8 | import io.netty.channel.nio.NioEventLoopGroup; 9 | import io.netty.channel.socket.nio.NioServerSocketChannel; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.stereotype.Component; 14 | 15 | import javax.annotation.PostConstruct; 16 | import javax.annotation.PreDestroy; 17 | import java.net.InetSocketAddress; 18 | 19 | /** 20 | * Created by haoxy on 2018/10/17. 21 | * E-mail:hxyHelloWorld@163.com 22 | * github:https://github.com/haoxiaoyong1014 23 | */ 24 | @Component 25 | public class HeartBeatServer { 26 | 27 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartBeatServer.class); 28 | /** 29 | * NioEventLoopGroup是一个处理I / O操作的多线程事件循环。 Netty为不同类型的传输提供各种EventLoopGroup实现。 30 | * 我们在此示例中实现了服务器端应用程序,因此将使用两个NioEventLoopGroup。第一个,通常称为“老板”,接受传入连接。第二个,通常称为“工人”, 31 | * 一旦老板接受连接并将接受的连接注册到工作人员,就处理被接受连接的流量。使用了多少个线程以及它们如何映射到创建的Channels取决于EventLoopGroup实现,甚至可以通过构造函数进行配置。 32 | */ 33 | private EventLoopGroup boss = new NioEventLoopGroup(); 34 | private EventLoopGroup work = new NioEventLoopGroup(); 35 | 36 | @Value("${netty.server.port}") 37 | private int nettyPort; 38 | 39 | /** 40 | * 启动 Netty 41 | * 42 | * @return 43 | * @throws InterruptedException 44 | */ 45 | @PostConstruct 46 | public void start() throws InterruptedException { 47 | ServerBootstrap bootstrap = new ServerBootstrap() 48 | .group(boss, work) 49 | .channel(NioServerSocketChannel.class) 50 | .localAddress(new InetSocketAddress(nettyPort)) 51 | //保持长连接 52 | .childOption(ChannelOption.SO_KEEPALIVE, true) 53 | .childHandler(new HeartbeatInitializer()); 54 | //绑定并开始接受传入的连接。 55 | ChannelFuture future = bootstrap.bind().sync(); 56 | if (future.isSuccess()) { 57 | LOGGER.info("启动 Netty 成功"); 58 | } 59 | } 60 | 61 | /** 62 | * 销毁 63 | */ 64 | @PreDestroy 65 | public void destroy() { 66 | boss.shutdownGracefully().syncUninterruptibly(); 67 | work.shutdownGracefully().syncUninterruptibly(); 68 | LOGGER.info("关闭 Netty 成功"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /netty-client/netty-client.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 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /netty-server/netty-server.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 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Netty介绍 2 | > **Netty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。 3 | “快速简便”并不意味着最终的应用程序会受到可维护性或性能问题的影响。Netty经过精心设计,具有丰富的协议,如FTP,SMTP,HTTP以及各种二进制和基于文本的传统协议。因此,Netty成功地找到了一种在不妥协的情况下实现易于开发,性能,稳定性和灵活性的方法。Netty 版本3x(稳定,jdk1.5+),4x(推荐,稳定,jdk1.6+),5x(不推荐),新版本不是很稳定,所以这里使用的是 Netty4x 版本** 4 | 5 | #### 项目依赖 6 | ```xml 7 | 8 | io.netty 9 | netty-all 10 | 4.1.21.Final 11 | 12 | ``` 13 | #### IdleStateHandler 14 | - Netty 可以使用 IdleStateHandler 来实现连接管理,当连接空闲时间太长(没有发送、接收消息)时则会触发一个事件,我们便可在该事件中实现心跳机制。 15 | 16 | #### 编写服务端 17 | ```java 18 | public class HeartBeatSimpleHandle extends SimpleChannelInboundHandler { 19 | 20 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartBeatSimpleHandle.class); 21 | private static final ByteBuf HEART_BEAT = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer(new CustomProtocol(123456L, "pong").toString(), CharsetUtil.UTF_8)); 22 | 23 | /** 24 | * 取消绑定 25 | * @param ctx 26 | * @throws Exception 27 | */ 28 | @Override 29 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 30 | NettySocketHolder.remove((NioSocketChannel) ctx.channel()); 31 | } 32 | 33 | @Override 34 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 35 | if (evt instanceof IdleStateEvent) { 36 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt; 37 | if (idleStateEvent.state() == IdleState.READER_IDLE) { 38 | LOGGER.info("已经5秒没有收到信息!"); 39 | //向客户端发送消息 40 | ctx.writeAndFlush(HEART_BEAT).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); 41 | } 42 | } 43 | super.userEventTriggered(ctx, evt); 44 | } 45 | 46 | @Override 47 | protected void channelRead0(ChannelHandlerContext ctx, CustomProtocol customProtocol) throws Exception { 48 | LOGGER.info("收到customProtocol={}", customProtocol); 49 | //我们调用writeAndFlush(Object)来逐字写入接收到的消息并刷新线路 50 | //ctx.writeAndFlush(customProtocol); 51 | //保存客户端与 Channel 之间的关系 52 | NettySocketHolder.put(customProtocol.getId(), (NioSocketChannel) ctx.channel()); 53 | } 54 | } 55 | 56 | ``` 57 | **对上面代码简要说明:** 58 | `HeartBeatSimpleHandle`继承了 ChannelInboundHandlerAdapter 的一个扩展(SimpleChannelInboundHandler), 59 | 而ChannelInboundHandlerAdapter是ChannelInboundHandler的一个实现 60 | ChannelInboundHandler提供了可以重写的各种事件处理程序方法,包括channelRead0()方法. 61 | 目前,只需继承 SimpleChannelInboundHandler或ChannelInboundHandlerAdapter 而不是自己实现处理程序接口。 62 | 我们重写了channelRead0()方法,每当接收到新数据时,都会使用收到的消息调用此方法。 63 | 当有多个客户端连上来时,服务端需要区分开,不然响应消息就会发生混乱。 64 | 所以每当有个连接上来的时候,我们都将当前的 Channel 与连上的客户端 ID 进行关联(因此每个连上的客户端 ID 都必须唯一)。 65 | 这里采用了一个 Map 来保存这个关系,并且在断开连接时自动取消这个关联。 66 | ```java 67 | public class NettySocketHolder { 68 | 69 | private static final Map MAP = new ConcurrentHashMap<>(16); 70 | 71 | public static void put(Long id, NioSocketChannel socketChannel) { 72 | MAP.put(id, socketChannel); 73 | } 74 | 75 | public static NioSocketChannel get(Long id) { 76 | return MAP.get(id); 77 | } 78 | 79 | public static Map getMAP() { 80 | return MAP; 81 | } 82 | 83 | public static void remove(NioSocketChannel nioSocketChannel) { 84 | MAP.entrySet().stream().filter(entry -> entry.getValue() == nioSocketChannel).forEach(entry -> MAP.remove(entry.getKey())); 85 | } 86 | } 87 | ``` 88 | * 这里使用了jdk1.8的Lambda 表达式 89 | #### 启动引导程序 90 | 91 | ```java 92 | @Component 93 | public class HeartBeatServer { 94 | 95 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartBeatServer.class); 96 | private EventLoopGroup boss = new NioEventLoopGroup(); //(1) 97 | private EventLoopGroup work = new NioEventLoopGroup(); 98 | 99 | @Value("${netty.server.port}") 100 | private int nettyPort; 101 | 102 | /** 103 | * 启动 Netty 104 | * 105 | * @return 106 | * @throws InterruptedException 107 | */ 108 | @PostConstruct 109 | public void start() throws InterruptedException { 110 | ServerBootstrap bootstrap = new ServerBootstrap() //(2) 111 | .group(boss, work) 112 | .channel(NioServerSocketChannel.class)// (3) 113 | .localAddress(new InetSocketAddress(nettyPort)) 114 | //保持长连接 115 | .childOption(ChannelOption.SO_KEEPALIVE, true)//(4) 116 | .childHandler(new HeartbeatInitializer());// (5) 117 | //绑定并开始接受传入的连接。 118 | ChannelFuture future = bootstrap.bind().sync();//(6) 119 | if (future.isSuccess()) { 120 | LOGGER.info("启动 Netty 成功"); 121 | } 122 | } 123 | 124 | /** 125 | * 销毁 126 | */ 127 | @PreDestroy 128 | public void destroy() { //(7) 129 | boss.shutdownGracefully().syncUninterruptibly(); 130 | work.shutdownGracefully().syncUninterruptibly(); 131 | LOGGER.info("关闭 Netty 成功"); 132 | } 133 | } 134 | ``` 135 | **对上面代码进行简要说明** 136 | 137 | (1),NioEventLoopGroup是一个处理I / O操作的多线程事件循环。 Netty为不同类型的传输提供各种EventLoopGroup实现。我们在此示例中实现了服务器端应用程序,因此将使用两个NioEventLoopGroup。第一个,通常称为“老板”,接受传入连接。第二个,通常称为“工人”,一旦老板接受连接并将接受的连接注册到工作人员,就处理被接受连接的流量。使用了多少个线程以及它们如何映射到创建的Channels取决于EventLoopGroup实现,甚至可以通过构造函数进行配置。 138 | 139 | (2),ServerBootstrap是一个设置服务器的帮助程序类。 140 | 141 | (3), 在这里,我们指定使用`NioServerSocketChannel`类,该类用于实例化新的Channel以接受传入的连接。 142 | 143 | (4),保持长连接 144 | 145 | (5), childHandler()方法需要一个ChannelInitializer类,ChannelInitializer是一个特殊的处理程序,旨在帮助用户配置新的Channel,您最有可能希望通过添加一些处理程序(如DiscardServerHandler)来配置新Channel的ChannelPipeline,以实现您的网络应用程序。 随着应用程序变得复杂,您可能会向管道添加更多处理程序,并最终将此匿名类提取到顶级类中。 146 | 这里我们用HeartbeatInitializer类继承了ChannelInitializer类并重写了initChannel()方法 147 | 148 | ```java 149 | public class HeartbeatInitializer extends ChannelInitializer { 150 | @Override 151 | protected void initChannel(Channel channel) throws Exception { 152 | channel.pipeline() 153 | //五秒没有收到消息 将IdleStateHandler 添加到 ChannelPipeline 中 154 | .addLast(new IdleStateHandler(5, 0, 0))//(8) 155 | .addLast(new HeartbeatDecoder())//(9) 156 | .addLast(new HeartBeatSimpleHandle());//(10) 157 | } 158 | } 159 | ``` 160 | (6).绑定到端口并启动服务器。 161 | 162 | (7).当程序关闭时优雅的关闭 Neety 163 | 164 | (8).将IdleStateHandler 添加到 ChannelPipeline 中,也会有一个定时任务,每5秒校验一次是否有收到消息,否则就主动发送一次请求。 165 | 166 | (9),服务端解码器,服务端与客户端采用的是自定义的 POJO 进行通讯的,所以需要在客户端进行编码,服务端进行解码,也都只需要各自实现一个编解码器即可。(下面也会说到) 167 | 168 | ```java 169 | public class HeartbeatDecoder extends ByteToMessageDecoder { 170 | @Override 171 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { 172 | long id = byteBuf.readLong(); 173 | byte[] bytes = new byte[byteBuf.readableBytes()]; 174 | byteBuf.readBytes(bytes); 175 | String content = new String(bytes); 176 | CustomProtocol customProtocol = new CustomProtocol(); 177 | customProtocol.setId(id); 178 | customProtocol.setContent(content); 179 | list.add(customProtocol); 180 | } 181 | } 182 | ``` 183 | (10),`HeartBeatSimpleHandle`继承了 ChannelInboundHandlerAdapter 的一个扩展(SimpleChannelInboundHandler) 184 | 185 | #### 编写客户端 186 | * 当客户端空闲了 N 秒没有给服务端发送消息时会自动发送一个心跳来维持连接。 187 | 188 | ```java 189 | /** 190 | * Created by haoxy on 2018/10/17. 191 | * E-mail:hxyHelloWorld@163.com 192 | * github:https://github.com/haoxiaoyong1014 193 | */ 194 | public class EchoClientHandle extends SimpleChannelInboundHandler { 195 | 196 | private final static Logger LOGGER = LoggerFactory.getLogger(EchoClientHandle.class); 197 | 198 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 199 | if (evt instanceof IdleStateEvent) { 200 | IdleStateEvent idleStateEvent = (IdleStateEvent) evt; 201 | if (idleStateEvent.state() == IdleState.WRITER_IDLE) { 202 | LOGGER.info("已经10秒没收到消息了"); 203 | //向服务端发送消息 204 | CustomProtocol heartBeat = SpringBeanFactory.getBean("heartBeat",CustomProtocol.class); 205 | ctx.writeAndFlush(heartBeat).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); 206 | } 207 | 208 | } 209 | super.userEventTriggered(ctx, evt); 210 | } 211 | 212 | /** 213 | * 每当从服务端接收到新数据时,都会使用收到的消息调用此方法 channelRead0(),在此示例中,接收消息的类型是ByteBuf。 214 | * @param channelHandlerContext 215 | * @param byteBuf 216 | * @throws Exception 217 | */ 218 | @Override 219 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { 220 | //从服务端收到消息时被调用 221 | LOGGER.info("客户端收到消息={}", byteBuf.toString(CharsetUtil.UTF_8)); 222 | } 223 | } 224 | 225 | ``` 226 | **对上面代码简要说明:** 227 | EchoClientHandle继承了 ChannelInboundHandlerAdapter 的一个扩展(SimpleChannelInboundHandler), 228 | 而ChannelInboundHandlerAdapter是ChannelInboundHandler的一个实现 229 | ChannelInboundHandler提供了可以重写的各种事件处理程序方法,包括channelRead0()方法. 230 | 目前,只需继承 SimpleChannelInboundHandler或ChannelInboundHandlerAdapter 而不是自己实现处理程序接口。 231 | 我们重写了channelRead0()方法,每当接收到新数据时,都会使用收到的消息调用此方法。 232 | 由于整合了 SpringBoot,在这里我们向服务端发送的是一个 单例的 Bean(上面所说的 pojo),所涉及到的类有: 233 | 234 | **SpringBeanFactory** 235 | ```java 236 | @Component 237 | public final class SpringBeanFactory implements ApplicationContextAware { 238 | 239 | private static ApplicationContext context; 240 | 241 | public static T getBean(Class c){ 242 | return context.getBean(c); 243 | } 244 | 245 | 246 | public static T getBean(String name,Class clazz){ 247 | return context.getBean(name,clazz); 248 | } 249 | 250 | @Override 251 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 252 | context = applicationContext; 253 | } 254 | } 255 | 256 | ``` 257 | **CustomProtocol** 258 | ```java 259 | public class CustomProtocol implements Serializable { 260 | private static final long serialVersionUID = 290429819350651974L; 261 | private long id; 262 | private String content; 263 | //省去 get set方法 264 | ``` 265 | **HeartBeatConfig** 266 | * 将CustomProtocol设置为一个 Bean,并赋值 267 | ```java 268 | @Configuration 269 | public class HeartBeatConfig { 270 | 271 | @Value("${channel.id}") 272 | private long id; 273 | 274 | @Bean(value = "heartBeat") 275 | public CustomProtocol heartBeat(){ 276 | return new CustomProtocol(id,"ping") ; 277 | } 278 | } 279 | ``` 280 | **当然我们还需要一个启动引导类** 281 | ```java 282 | @Component 283 | public class HeartbeatClient { 284 | private final static Logger LOGGER = LoggerFactory.getLogger(HeartbeatClient.class); 285 | private EventLoopGroup group = new NioEventLoopGroup();//(1) 286 | @Value("${netty.server.port}") 287 | private int nettyPort; 288 | @Value("${netty.server.host}") 289 | private String host; 290 | 291 | private SocketChannel socketChannel; 292 | 293 | @PostConstruct 294 | public void start() throws InterruptedException { 295 | Bootstrap bootstrap = new Bootstrap();//(2) 296 | /** 297 | * NioSocketChannel用于创建客户端通道,而不是NioServerSocketChannel。 298 | * 请注意,我们不像在ServerBootstrap中那样使用childOption(),因为客户端SocketChannel没有父服务器。 299 | */ 300 | bootstrap.group(group) 301 | .channel(NioSocketChannel.class)//(3) 302 | .handler(new CustomerHandleInitializer());//(4) 303 | /** 304 | * 启动客户端 305 | * 我们应该调用connect()方法而不是bind()方法。 306 | */ 307 | ChannelFuture future = bootstrap.connect(host, nettyPort).sync();//(5) 308 | if (future.isSuccess()) { 309 | LOGGER.info("启动 Netty 成功"); 310 | } 311 | 312 | socketChannel = (SocketChannel) future.channel(); 313 | 314 | } 315 | 316 | } 317 | ``` 318 | **对上面代码进行简要说明:** 319 | Netty中服务器和客户端之间最大和唯一的区别是使用了不同的Bootstrap和Channel实现。 320 | 321 | (1),如果只指定一个EventLoopGroup,它将同时用作boss组和worker组。 但是,老板工作者不会用于客户端。 322 | 323 | (2),Bootstrap(客户端使用)类似于ServerBootstrap(服务端使用),不同之处在于它适用于非服务器通道 324 | 325 | (3),NioSocketChannel用于创建客户端通道,而不是NioServerSocketChannel(服务端) 326 | 327 | (4),客户端handler()方法与服务端childHandler()同样都是需要一个ChannelInitializer类,ChannelInitializer是一个特殊的处理程序,这里用CustomerHandleInitializer继承了ChannelInitializer 328 | 329 | ```java 330 | public class CustomerHandleInitializer extends ChannelInitializer { 331 | @Override 332 | protected void initChannel(Channel channel) throws Exception { 333 | channel.pipeline() 334 | //10 秒没发送消息 将IdleStateHandler 添加到 ChannelPipeline 中 335 | .addLast(new IdleStateHandler(0, 10, 0))//(6) 336 | .addLast(new HeartbeatEncode())//(7) 337 | .addLast(new EchoClientHandle());//(8) 338 | } 339 | } 340 | ``` 341 | (5),我们这里应该调用connect()方法而不是bind()方法。 342 | 343 | (6),客户端的心跳其实也是类似,也需要在 ChannelPipeline 中添加一个 IdleStateHandler 344 | 345 | (7),客户端编码器 346 | 347 | ```java 348 | public class HeartbeatEncode extends MessageToByteEncoder { 349 | @Override 350 | protected void encode(ChannelHandlerContext channelHandlerContext, CustomProtocol customProtocol, ByteBuf byteBuf) throws Exception { 351 | byteBuf.writeLong(customProtocol.getId()) ; 352 | byteBuf.writeBytes(customProtocol.getContent().getBytes()) ; 353 | } 354 | } 355 | ``` 356 | (8),EchoClientHandle继承了 ChannelInboundHandlerAdapter 的一个扩展(SimpleChannelInboundHandler) 357 | 358 | **这里贴出客户端与服务端的配置文件** 359 | * 客户端 360 | ```java 361 | # web port 362 | server.port=8082 363 | # 通道 ID 364 | channel.id=100 365 | 366 | netty.server.host=127.0.0.1 367 | netty.server.port=11211 368 | ``` 369 | * 服务端 370 | ```java 371 | # web port 372 | server.port=8081 373 | netty.server.port=11211 374 | ``` 375 | **启动客户端以及服务端** 376 | ![image](https://github.com/haoxiaoyong1014/best-pay-demo/raw/master/src/main/java/com/github/lly835/Images/x1.jpeg) 377 | ![image](https://github.com/haoxiaoyong1014/best-pay-demo/raw/master/src/main/java/com/github/lly835/Images/x2.jpeg) 378 | 379 | 380 | 381 | * [x] [参考文章](https://crossoverjie.top/2018/05/24/netty/Netty(1)TCP-Heartbeat/) 382 | 383 | * [x] [需要了解更多参考](https://netty.io/index.html) 384 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 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 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 172 | 173 | 174 | 175 | HeartbeatInitializer 176 | HeartbeatDecoder 177 | ping 178 | MessageToByteEncoder 179 | ByteToMessageDecoder 180 | 123456 181 | channelRead 182 | 发送消息 183 | 184 | 185 | 186 | 188 | 189 | 192 | 193 | 194 | 218 | 219 | 220 | 221 | 222 | true 223 | DEFINITION_ORDER 224 | 225 | 226 | 232 | 237 | 238 | 239 | 241 | 242 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | Abstraction issuesJava 256 | 257 | 258 | Android > Lint > Correctness 259 | 260 | 261 | Google Web Toolkit issues 262 | 263 | 264 | Gradle 265 | 266 | 267 | Java 268 | 269 | 270 | Kotlin 271 | 272 | 273 | Maven 274 | 275 | 276 | OSGi 277 | 278 | 279 | Probable bugsGradle 280 | 281 | 282 | Security issuesJava 283 | 284 | 285 | Serialization issuesJava 286 | 287 | 288 | 289 | 290 | SerializableHasSerialVersionUIDField 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 |