前言,

说明

引入netty的pom

     <!-- netty --><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.6.Final</version></dependency>

然后下面要写四个类,
SocketServer  ---服务器启动类
SocketServerHandler ---服务器消息处理
SocketClientHandlerTest ---测试使用的的客户端消息处理
SocketClientTest ---测试使用的客户端启动类

看这几个类,handle是启动类中的一个小部件,这个是2者的关系,具体代码如下

SocketServer

/*** Copyright (C), 2015-2018* FileName: SocketServer* Author:   zhao* Date:     2018/6/10 21:26* Description: netty服务器* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.net;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;/*** 〈一句话功能简述〉<br>* 〈netty服务器〉** @author zhao* @create 2018/6/10* @since 1.0.0*/
public class SocketServer {private static final Logger logger = LoggerFactory.getLogger(SocketServer.class);private static final String IP = "127.0.0.1";private static final int PORT = 8088;/*** 分配用于处理业务的线程组数量*/private static final int BIS_GROUP_SIZE = Runtime.getRuntime().availableProcessors() * 2;/*** 每个线程组中线程的数量*/private static final int WORK_GROUP_SIZE = 4;private static EventLoopGroup bossGroup = new NioEventLoopGroup(BIS_GROUP_SIZE);private static EventLoopGroup workerGroup = new NioEventLoopGroup(WORK_GROUP_SIZE);public  void run() throws Exception {ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup);bootstrap.channel(NioServerSocketChannel.class);bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 以("\n")为结尾分割的 解码器pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));pipeline.addLast("decoder", new StringDecoder());pipeline.addLast("encoder", new StringEncoder());pipeline.addLast(new SocketServerHandler());}});bootstrap.bind(IP, PORT).sync();logger.info("Socket服务器已启动完成");}protected static void shutdown() {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}public static void main(String[] args) throws Exception {logger.info("开始启动Socket服务器...");new SocketServer().run();}
}

SocketServerHandler

/*** Copyright (C), 2015-2018* FileName: SocketServerHandler* Author:   zhao* Date:     2018/6/10 21:27* Description: SocketServer的消息处理类* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.net;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;/*** 〈一句话功能简述〉<br>* 〈SocketServer的消息处理类〉** @author zhao* @create 2018/6/10* @since 1.0.0*/
public class SocketServerHandler extends SimpleChannelInboundHandler<String> {private static final Logger logger = LoggerFactory.getLogger(SocketServer.class);@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {logger.debug("异常发生", throwable);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {super.channelRead(ctx, msg);}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {logger.info("数据内容:data=" + msg);String result = "小李,我是服务器,我收到你的信息了。";//这行很重要,StringDecoder以这个作为消息分割,// 如果没有换行符的话,服务端就没办法接受到result += "\r\n";ctx.writeAndFlush(result);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {logger.info("建立连接");super.channelActive(ctx);}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {logger.info("连接断开");super.channelInactive(ctx);}
}

SocketClientHandlerTest

/*** Copyright (C), 2015-2018* FileName: SocketClientHandlerTest* Author:   zhao* Date:     2018/6/10 21:36* Description: SocketClient的测试类* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.net;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;/*** 〈一句话功能简述〉<br>* 〈SocketClient的测试类〉** @author zhao* @create 2018/6/10* @since 1.0.0*/
public class SocketClientHandlerTest extends SimpleChannelInboundHandler<String> {private static final Logger logger = LoggerFactory.getLogger(SocketClientTest.class);@Overridepublic void exceptionCaught(ChannelHandlerContext arg0, Throwable arg1) {logger.info("异常发生", arg1);}@Overridepublic void channelRead(ChannelHandlerContext arg0, Object msg) throws Exception {super.channelRead(arg0, msg);}@Overrideprotected void channelRead0(ChannelHandlerContext arg0, String data) {logger.info("数据内容:data=" + data);}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {logger.info("客户端连接建立");super.channelActive(ctx);}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {logger.info("客户端连接断开");super.channelInactive(ctx);}
}

SocketClientTest

/*** Copyright (C), 2015-2018* FileName: SocketServerTest* Author:   zhao* Date:     2018/6/10 21:35* Description: SocketServer的测试类* History:* <author>          <time>          <version>          <desc>* 作者姓名           修改时间           版本号              描述*/
package com.lizhaoblog.net;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;/*** 〈一句话功能简述〉<br>* 〈SocketServer的测试类〉** @author zhao* @create 2018/6/10* @since 1.0.0*/
public class SocketClientTest {private static final Logger logger = LoggerFactory.getLogger(SocketClientTest.class);private static final String IP = "127.0.0.1";private static final int PORT = 8088;private static EventLoopGroup group = new NioEventLoopGroup();@SuppressWarnings("rawtypes")protected static void run() throws Exception {Bootstrap bootstrap = new Bootstrap();bootstrap.group(group);bootstrap.channel(NioSocketChannel.class);bootstrap.handler(new ChannelInitializer() {@Overrideprotected void initChannel(Channel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();/** 这个地方的 必须和服务端对应上。否则无法正常解码和编码** 解码和编码 我将会在下一张为大家详细的讲解。再次暂时不做详细的描述** */pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));pipeline.addLast("decoder", new StringDecoder());pipeline.addLast("encoder", new StringEncoder());pipeline.addLast(new SocketClientHandlerTest());}});// 连接服务端ChannelFuture channelFuture = bootstrap.connect(IP, PORT).sync();String msg = "小王,我是客户端";//这行很重要,StringDecoder以这个作为消息分割,// 如果没有换行符的话,服务端就没办法接受到msg += "\r\n";channelFuture.channel().writeAndFlush(msg);logger.info("向Socket服务器发送数据:" + msg);channelFuture.channel().closeFuture().sync();}public static void main(String[] args) {logger.info("开始连接Socket服务器...");try {run();} catch (Exception e) {e.printStackTrace();} finally {group.shutdownGracefully();}}
}

测试方法:先启动Main函数中的main或者SocketServer中的main函数,2者一样,然后启动SocketClientTest中的函数,能做到收发就ok了,像这样

服务器2018-06-10 21:48:45.763 INFO  com.lizhaoblog.net.SocketServer - Socket服务器已启动完成2018-06-10 21:48:51.277 DEBUG io.netty.buffer.AbstractByteBuf - -Dio.netty.buffer.bytebuf.checkAccessible: true2018-06-10 21:48:51.281 DEBUG io.netty.util.ResourceLeakDetectorFactory - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@4a38e4462018-06-10 21:48:51.291 INFO  com.lizhaoblog.net.SocketServer - 建立连接2018-06-10 21:48:51.303 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 327682018-06-10 21:48:51.303 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 22018-06-10 21:48:51.303 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 162018-06-10 21:48:51.303 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 82018-06-10 21:48:51.329 INFO  com.lizhaoblog.net.SocketServer - 数据内容:data=小王,我是客户端客户端2018-06-10 21:48:51.246 INFO  com.lizhaoblog.net.SocketClientTest - 客户端连接建立2018-06-10 21:48:51.251 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxCapacityPerThread: 327682018-06-10 21:48:51.251 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.maxSharedCapacityFactor: 22018-06-10 21:48:51.251 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.linkCapacity: 162018-06-10 21:48:51.251 DEBUG io.netty.util.Recycler - -Dio.netty.recycler.ratio: 82018-06-10 21:48:51.255 INFO  com.lizhaoblog.net.SocketClientTest - 向Socket服务器发送数据:小王,我是客户端2018-06-10 21:48:51.340 INFO  com.lizhaoblog.net.SocketClientTest - 数据内容:data=小李,我是服务器,我收到你的信息了。2018-06-10 21:49:02.674 INFO  com.lizhaoblog.net.SocketClientTest - 异常发生

接下来就是改造下简单的实例了,spring框架在java体系中确实是至关重要的一个东西,所以下一篇应该是将netty和spring结合起来。

上面的代码在码云上 https://gitee.com/lizhaoandroid/JgServer
可以加qq群一起探讨Java游戏服务器开发的相关知识 676231564

java游戏服务器开发之四--通讯框架netty相关推荐

  1. Java游戏服务器开发之二--导航帖

    Java游戏服务器开发之三--日志         Java游戏服务器开发之四--通讯框架netty Java游戏服务器开发之五--使用工厂模式生成netty Java游戏服务器开发之六--整合spr ...

  2. java游戏服务器开发之八--网络事件监听器

    java游戏服务器开发之八-网络事件监听器 网络事件监听器,将网络变化交由NetworkListener处理 可以看到,我们现在所有的逻辑都是写在TcpMessageStringHandler里面, ...

  3. java游戏服务器的开发和维护,java游戏服务器开发

    java游戏服务器开发 内容精选 换一换 开发者基于Atlas 200 DK进行AI应用开发前,需要在制作SD卡时准备的Ubuntu服务器中部署开发环境,有以下两种场景:部署MindStudio,基于 ...

  4. Java游戏服务器开发之十二--数据库连接整合mybatis

    应该比较让人关心的还有一个就是数据存储的问题了.   下面将会介绍连接数据库的相关内容   使用的是mysql数据库,框架中将使用mybatis   这里介绍时假设各位都使用或者了解过mysql. 1 ...

  5. Java游戏服务器开发之概念扫盲

    入行缘由 在2017年我正式的从web转Java游戏服务器开发.那个时候机缘巧合的投了一家使用Java语言开发游戏服务器的企业,当时的老板还问我为什么从web转游戏开发.当时我的回答还是历历在目:我喜 ...

  6. 《深度解析Java游戏服务器开发》源码

    不知什么原因,出售的<深度解析Java游戏服务器开发>一书中,没有给出源码,这里补上,源码已经上传至github: https://github.com/hjcenry/JavaServe ...

  7. Java游戏服务器开发之二十--xml配置文件

    Java游戏服务器开发之二十--xml配置文件     游戏中使用的配置文件很多     像游戏中的关卡,英雄等级,装备之类都是使用配置文件(xml等)     比如有一个装备,配置表中有一条记录,数 ...

  8. 学习JAVA游戏服务器开发需要了解的情况

    一,游戏服务器开发的工作介绍 近来遇到有很多人想从其它开发领域转到游戏服务器开发行业上来,他们或许觉得游戏服务器开发工资高,或许觉得做游戏服务器需要掌握的技术更高级,可以锻炼自己,或许觉得想换个环境等 ...

  9. 如何学习java游戏服务器开发?

    为什么游戏服务器很多都用Java开发 Java 做游戏服务器开发的优势还是很多的,<我的世界>的服务器就是Java开发的.Java技术比较成熟,大数据,云计算,网站App后台,基本都采用J ...

最新文章

  1. VS2019 开发第一个Windows驱动程序
  2. 用户案例 - 3Cs
  3. Paper:《Multimodal Machine Learning: A Survey and Taxonomy,多模态机器学习:综述与分类》翻译与解读
  4. 推荐12款非常有用的流行 jQuery 插件
  5. 泰安第一中学2021年高考成绩查询,等级考第一天结束 泰安部分考生已完成2021年高考...
  6. php配置了扩展为什么不生效,php安装扩展模块后,重启不生效的原因及解决办法...
  7. 纤亿通解读—光纤通信系统工作原理
  8. LOTO示波器 实测 开环增益频响曲线/电源环路响应稳定性
  9. 独立站运营到底要做什么!
  10. JAVA大写金额转小写金额过程
  11. 如何把图片的文字转换成word
  12. 图片去水印在线-图片去水印无痕迹的app
  13. 在form表单中添加一个隐藏的reset按钮,
  14. element-ui 表格总计有多行的情况
  15. RBP系统管理之地区管理
  16. 边沿触发是什么意思_epoll边缘触发模式
  17. 【博弈论】纳什定理及其证明
  18. mysql intersect 使用方法_MySQL查询优化一例——也说说 Using intersect
  19. 日志收集平台Graylog2以及Nxlog的安装与配置(基于docker)
  20. CURL -命令行下载工具

热门文章

  1. 如何将百度搜索嵌入到站点中!
  2. Firefox浏览器出现“连接被重置”的问题
  3. 一个不小心就串场了 ~ mingw32-gcc和tdm-gcc的一处不同引起的依赖错误
  4. 【微信小程序】解决canvas组件永远在最高层问题
  5. 外边距设置居中HTML,margin水平居中 关于margin的居中问题
  6. excel每页小计累计_您还需要Excel小计吗?
  7. 未来几年Python就业前景如何
  8. 人工智能复试面试题总结
  9. 防火墙双击热备技术(理论)
  10. 有没有必要考取PMP?