源码下载 -> 提取码  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. 神兽、佛祖保佑,代码全程无bug

    ''' ━━━━━━神兽出没━━━━━━ ┏┓ ┏┓ ┏┛┻━━━━━┛┻┓ ┃ ┃ ┃ ━ ┃ ┃ ┳┛ ┗┳ ┃ ┃ ┃ ┃ ┻ ┃ ┃ ┃ ┗━┓ ┏━┛ Code is far away fr ...

  2. 20191003 「HZOJ NOIP2019 Round #8」20191003模拟

    综述 试题为常州集训2019SCDay2 得分\(100+30(0)+28\) 时之终结 问题描述 HZOJ1310 题解 构造题. 发现部分分有一档是 \(Y\) 是 \(2^x\) ,于是自然想到 ...

  3. C++中整型变量的存储大小和范围

    一.代码查看 #include <iostream> #include <climits> using namespace std; int main(void) { cout ...

  4. Ztree + bootstarp-table 使用

    Ztree + bootstarp-table  使用 一. Ztree 1.引入js/css文件  Ztree官网 <!--ztree--> <link rel="sty ...

  5. [LeetCode] 907. Sum of Subarray Minimums 子数组最小值之和

    Given an array of integers A, find the sum of min(B), where B ranges over every (contiguous) subarra ...

  6. [LeetCode] 494. Target Sum 目标和

    You are given a list of non-negative integers, a1, a2, ..., an, and a target, S. Now you have 2 symb ...

  7. [LeetCode] 457. Circular Array Loop 环形数组循环

    You are given a circular array nums of positive and negative integers. If a number k at an index is ...

  8. bcrypt 加密算法

    MD5 的特性 MD5 是一种加密算法,在调用这个算法的时候,提供一个密码的明文, 调用的结果,得到一个 32 位长度的密文: MD5 算法的特性:相同的字符串,如果多次调用 md5 算法,得到的结果 ...

  9. 解决SpringDataJpa实体类中属性顺序与数据库中生成字段顺序不一致的问题

    一.在application.yml配置中添加数据库根据实体类自动创建数据库表的配置(这里数据库采用MySQL数据库) jpa: database: MYSQL show-sql: true #Hib ...

  10. torch_09_DCGAN_注意的细节

    DCGAN github链接:https://github.com/darr/DCGAN DCGAN:1.在一次epoch中,如果第i批的i能够整除every_print,则打印到output文件中( ...