源码下载 -> 提取码  QQ:505645074


Netty 是一个高性能、异步事件驱动的 NIO 框架,它提供了对 TCP、UDP 和文件传输的支持,作为一个异步 NIO 框架,Netty 的所有 IO 操作都是异步非阻塞的,通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO 操作结果。

作为当前最流行的 NIO 框架,Netty 在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于 Netty 的 NIO 框架构建。

协议解析代码:

package nettyserver;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerContext;

import io.netty.channel.ChannelInboundHandlerAdapter;

import io.netty.handler.timeout.IdleStateEvent;

import io.netty.util.ReferenceCountUtil;

import java.util.HashMap;

import java.util.Map;

class MyInHandler extends ChannelInboundHandlerAdapter {

final byte HEAD1 = 0x48;// H

final byte HEAD2 = 0x54;// T

final byte HEAD3 = 0x45;// E

final byte HEAD4 = 0x4D;// M

final byte HEAD5 = 0x50;// P

final byte HEAD6 = 0x3D;// =

public static final String SPLIT1 = "#";

public static Map<String, io.netty.buffer.ByteBuf> dicSn2Buffer = new HashMap<>();

// HTEMP=0026#1533022506#Meter-001#01##

@Override

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)

{

// 当出现异常就关闭连接

//cause.printStackTrace();

RemoveClient(ctx, "exceptionCaught");

}

@Override

public void channelActive(io.netty.channel.ChannelHandlerContext ctx) throws Exception

{

CTxtHelp.AppendLog("客户端已经连接,sn:" + GetSN(ctx));

}

@Override

public void channelInactive(io.netty.channel.ChannelHandlerContext ctx) throws Exception

{

RemoveClient(ctx, "channelInactive");

}

@Override

public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception

{

if (evt instanceof IdleStateEvent)

{

String type = "未知";

IdleStateEvent event = (IdleStateEvent) evt;

if (null != event.state())

{

switch (event.state())

{

case READER_IDLE: type = "read idle"; break;

case WRITER_IDLE: type = "write idle"; break;

case ALL_IDLE: type = "all idle"; break;

default: break;

}

}

RemoveClient(ctx, "超时退出(" + type + ")");

}

else

{

super.userEventTriggered(ctx, evt);

}

}

@Override

public void channelRead(io.netty.channel.ChannelHandlerContext ctx, Object msg)

{

if (!ctx.channel().isActive()) return;

String sn = GetSN(ctx);

if(!dicSn2Buffer.containsKey(sn)) dicSn2Buffer.put(sn, Unpooled.buffer(1024));

io.netty.buffer.ByteBuf oldBuffer = dicSn2Buffer.get(sn);

if (null != msg)

{

io.netty.buffer.ByteBuf recvBuffer = (ByteBuf) msg;

int size = recvBuffer.readableBytes();

if (size > 0)

{

//recvBuffer.markReaderIndex();

oldBuffer.writeBytes(recvBuffer);

ReferenceCountUtil.release(recvBuffer);

//recvBuffer.resetReaderIndex();

//byte[] recv = new byte[size];

//recvBuffer.readBytes(recv);

//CTxtHelp.AppendLog("接收数据:" + CDataHelper.ArrayByteToString(recv));

}

}

byte head1 = 0; byte head2 = 0; byte head3 = 0; byte head4 = 0; byte head5 = 0; byte head6 = 0;

while (oldBuffer.isReadable())

{

oldBuffer.markReaderIndex();

head1 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; } // 掉包处理

if (HEAD1 == head1)// 垃圾包处理

{

head2 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; }

head3 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; }

head4 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; }

head5 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; }

head6 = oldBuffer.readByte(); if (!oldBuffer.isReadable()) { oldBuffer.resetReaderIndex(); return ; }

if (HEAD2 == head2 && HEAD3 == head3 && HEAD4 == head4 && HEAD5 == head5 && HEAD6 == head6)

{

break;

}

else

{

CTxtHelp.AppendLog("Error,Unable to parse the data2");

}

}

else

{

CTxtHelp.AppendLog("Error,Unable to parse the data1");

}

}

int lengthsize = 4;

if (GetWaitRecvRemain(oldBuffer, lengthsize)) { oldBuffer.resetReaderIndex(); return ; }

byte[] arrlen = new byte[lengthsize]; oldBuffer.readBytes(arrlen);

int lengthdata = CDataHelper.String2Int(CDataHelper.ArrayByteToString(arrlen));// if (-1 == len) return;

if (GetWaitRecvRemain(oldBuffer, lengthdata)) { oldBuffer.resetReaderIndex(); return ; }

byte[] source = new byte[lengthdata]; oldBuffer.readBytes(source);

String data = CDataHelper.ArrayByteToString(source);

CTxtHelp.AppendLog("解析后:" + data);

if (null == data || 0 == data.length() || data.length() - 1 != data.lastIndexOf(SPLIT1)) return;

data = data.substring(1, data.length() - 1);

String[] items = data.split(SPLIT1, -1);

if (null == items || 4 != items.length) return;

String uid = items[0];

String taskid = items[1];

int cmd = CDataHelper.String2Int(items[2]);

String content = items[3];

String back = "";

try

{

switch (cmd)

{

case 1: back = "ok"; break;

case 2: break;

case 3: break;

}

}

catch (Exception ex)

{

CTxtHelp.AppendLog("error@" + ex.getMessage());

}

if (!"".equals(back))

{

byte[] sendBuff = GetProtocol(uid, cmd, back);

ByteBuf out = ctx.alloc().directBuffer(sendBuff.length);

out.writeBytes(sendBuff);

ctx.channel().writeAndFlush(out);

}

if (!oldBuffer.isReadable())

{

oldBuffer.clear();

}

else

{

channelRead(ctx, null);

}

}

boolean GetWaitRecvRemain( io.netty.buffer.ByteBuf buf, int len) {

return buf.readerIndex() + len > buf.writerIndex();

}

String GetSN(io.netty.channel.ChannelHandlerContext ctx)

{

return ctx.channel().remoteAddress().toString().replace("/", "");

}

void RemoveClient(io.netty.channel.ChannelHandlerContext ctx, String errmsg)

{

String sn = GetSN(ctx);

CTxtHelp.AppendLog("客户端退出,errmsg:" + errmsg);

if(dicSn2Buffer.containsKey(sn)) {

io.netty.buffer.ByteBuf byteBuf = dicSn2Buffer.get(sn);

ReferenceCountUtil.release(byteBuf);

dicSn2Buffer.remove(sn);

}

ctx.close();

}

byte[] GetProtocol(String uid, int cmd, String msg)

{

String content = SPLIT1 + uid + SPLIT1 +

System.currentTimeMillis() + SPLIT1 +

CDataHelper.lpad(cmd, 2) + SPLIT1 +

msg + SPLIT1;

StringBuilder data = new StringBuilder();

data.append("HTEMP=");

data.append(CDataHelper.lpad(CDataHelper.GetStringLength(content), 4));

data.append(content);

return CDataHelper.StringToByte(data.toString());

}

String lpad(int number, int length) {

String f = "%0" + length + "d";

return String.format(f, number);

}

}

程序结构:

运行结果:

1. 包解析(正常包+掉包+粘包+垃圾包)

2. 超时清理链路

3. 并发测试

高性能TcpServer(Java) - Netty的更多相关文章

  1. Java Netty简介

    Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户netty.io(http:// ...

  2. [转帖]Java Netty简介

    Java Netty简介 https://www.cnblogs.com/ghj1976/p/3779820.html Posted on 2014-06-10 13:41 蝈蝈俊 阅读(2992) ...

  3. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  4. 【Jetlang】一个高性能的Java线程库

    actor  Jetlang 提供了一个高性能的Java线程库,该库是 JDK 1.5 中的 java.util.concurrent 包的补充,可用于基于并发消息机制的应用. .net的MS CCR ...

  5. JAVA语言之怎样写出高性能的Java代码?

    本文主要向大家介绍了JAVA语言之怎样写出高性能的 Java 代码?通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 在这篇文章中,我们将讨论几个有助于提升Java应用程序性能的方法.我 ...

  6. 项目-高性能TcpServer - 目录

    1.项目-高性能TcpServer - 1.网络通信协议 https://blog.csdn.net/arno1988/article/details/82463225 2.项目-高性能TcpServ ...

  7. 学习 java netty (一) -- java nio

    前言:近期在研究java netty这个网络框架,第一篇先介绍java的nio. java nio在jdk1.4引入,事实上也算比較早的了.主要引入非堵塞io和io多路复用.内部基于reactor模式 ...

  8. 高性能TcpServer(C#) - 1.网络通信协议

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

  9. 高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)

    高性能TcpServer(C#) - 1.网络通信协议 高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 高性能TcpS ...

随机推荐

  1. UiPath:Delay延迟执行,解决UiPath自动输入值不完整问题

    学习过程中出现点击按钮后,由于网页弹出框显示速度慢,造成输入值遗漏或者根本就没有输入问题. 查阅了一下,目前解决方法是在点击按钮后加一段延迟时间,等待他显示完整在输入值.如图 时间格式以秒为单位 00 ...

  2. ubuntu16.04安装docker图形管理界面portainer

    下载镜像 docker pull portainer/portainer 单机版运行 docker run -d --name portainer \ -p 9000:9000 \ --restart ...

  3. Github上 10 个开源免费且优秀的后台控制面板

    Web 开发中几乎的平台都需要一个后台管理,但是从零开发一套后台控制面板并不容易,幸运的是有很多开源免费的后台控制面板可以给开发者使用,那么有哪些优秀的开源免费的控制面板呢?我在 Github 上收集 ...

  4. vscode用服务打开html

    ①安装插件 此时右击会有: ②anywhere

  5. [LeetCode] 28. Implement strStr() 实现strStr()函数

    Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle ...

  6. STM32调试,发现HAL_Init();之后无法调试,甚至无法让程序停下来

    症状 最近开始学习STM32Cube,发现新建工程后无法正常调试,过了HAL_Init();之后就无法继续调试了. 无法进行让程序暂停以及停止等操作.并在输出窗口不断刷出 ERROR: Can not ...

  7. 2019年上-C语言程序设计-第1次blog作业

    准备工作(20分) 1.在博客园申请个人博客,以真实姓名和学号加入班级博客(链接地址) 2.关注邹欣老师博客(并寻找答案:邹欣老师是谁?是做什么的?).关注任课老师博客 3.注册登录中国大学MOOC网 ...

  8. 从头学一次J2EE笔记

    1.在Servlet3.5规范之前,Java Web 应用的绝大部分组件都通过web.xml 文件来配置管理, Servlet3.0 规范可通过Annotation来配置管理Web组件,因此web.x ...

  9. xunsearch强制刷新

    $index = $xs->index; $index->flushLogging(); 等价于 util/Indexer.php --flush-log demo

  10. 【题解】宫廷守卫 [P1263]

    [题解]宫廷守卫 [P1263] 传送门:宫廷守卫 \([P1263]\) [题目描述] 给出一个 \(n*m\) 的方格图,分别用整数 \(0,1,2\) 表示空地.陷阱.墙,空地上可以放置守卫,如 ...