所用jar包

netty-all-4.1.30.Final.jar 密码:rzwe

NettyConfig.java,存放连接的客户端

 import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor; public class NettyConfig { /**
* 存储每一个客户端接入进来时的channel对象
*/
public static ChannelGroup group = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); }

Server.java,netty配置信息

 import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; public class Server {
private int port;
private ServerSocketChannel serverSocketChannel; public Server(int port){
this.port = port;
bind();
} private void bind() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//服务端要建立两个group,一个负责接收客户端的连接,一个负责处理数据传输
//连接处理group
EventLoopGroup boss = new NioEventLoopGroup();
//事件处理group
EventLoopGroup worker = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
// 绑定处理group
bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
//保持连接数
.option(ChannelOption.SO_BACKLOG, 300)
//有数据立即发送
.option(ChannelOption.TCP_NODELAY, true)
//保持连接
.childOption(ChannelOption.SO_KEEPALIVE, true)
//处理新连接
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
// 增加任务处理
ChannelPipeline p = sc.pipeline();
p.addLast(
// //使用了netty自带的编码器和解码器
// new StringDecoder(),
// new StringEncoder(),
//心跳检测,读超时,写超时,读写超时
//new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS),
//自定义的处理器
new ServerHandler());
}
}); //绑定端口,同步等待成功
ChannelFuture future;
try {
future = bootstrap.bind(port).sync();
if (future.isSuccess()) {
serverSocketChannel = (ServerSocketChannel) future.channel();
System.out.println("服务端启动成功,端口:"+port);
} else {
System.out.println("服务端启动失败!");
} //等待服务监听端口关闭,就是由于这里会将线程阻塞,导致无法发送信息,所以我这里开了线程
future.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
}
finally {
//优雅地退出,释放线程池资源
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
});
thread.start();
} public void sendMessage(Object msg){
if(serverSocketChannel != null){
serverSocketChannel.writeAndFlush(msg);
}
} public static void main(String[] args) {
Server server = new Server(8088);
}
}

ServerHandler.java,业务处理

 import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; public class ServerHandler extends ChannelInboundHandlerAdapter { /**
* 客户端与服务端创建连接的时候调用
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端与服务端连接开始...");
NettyConfig.group.add(ctx.channel());
} /**
* 客户端与服务端断开连接时调用
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客户端与服务端连接关闭...");
NettyConfig.group.remove(ctx.channel());
} /**
* 服务端接收客户端发送过来的数据结束之后调用
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
System.out.println("信息接收完毕...");
} /**
* 工程出现异常的时候调用
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
} /**
* 服务端处理客户端websocket请求的核心方法,这里接收了客户端发来的信息
*/
@Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object info) throws Exception {
System.out.println("接收到了:"+info);
ByteBuf buf = (ByteBuf) info;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("接收客户端数据:" + body);
ByteBuf pingMessage = Unpooled.buffer();
pingMessage.writeBytes(req);
channelHandlerContext.writeAndFlush(pingMessage); //服务端使用这个就能向 每个连接上来的客户端群发消息
//NettyConfig.group.writeAndFlush(info);
// Iterator<Channel> iterator = NettyConfig.group.iterator();
// while(iterator.hasNext()){
// //打印出所有客户端的远程地址
// System.out.println((iterator.next()).remoteAddress());
// }
} }

使用网络调试助手进行连接测试 下载地址

https://www.wanpishe.top/detail?blogId=fc62fce2-020a-4815-8388-0903e4a54e1f

netty实现TCP长连接的更多相关文章

  1. 基于netty实现的长连接,心跳机制及重连机制

    技术:maven3.0.5 + netty4.1.33 + jdk1.8   概述 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速 ...

  2. 不仅仅是百万级TCP长连接框架 t-io

    t-io: 不仅仅是百万级TCP长连接框架 t-io是基于jdk aio实现的易学易用.稳定.性能强悍.将多线程运用到极致.内置功能丰富的即时通讯框架(广义上的即时通讯,并非指im),字母 t 寓意t ...

  3. Http 和TCP的关系,TCP长连接和短连接有什么区别?

    HTTP 协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用.由于HTTP在 ...

  4. TCP 长连接与短连接的区别

    TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,连接的建立是需要三次握手的 ...

  5. TCP长连接与短连接

    1.概念区别 所谓TCP短连接,是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接.也就是说TCP连接维持的时间比较短.一般银行网页数据交互都使用短连接.再比如说htt ...

  6. TCP长连接与短连接的区别

    http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html 1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,se ...

  7. 多进程解决datasnap支持的tcp长连接数量少的问题

    对于实时采集数据的项目,应用场景比如是这样的:5000客户端,每个客户端每隔500MS要给服务器上传一次数据. 大家知道,像INDY这种阻塞型的通信控件,所能支持的TCP长连接的一般地不能超过1000 ...

  8. TCP长连接与短连接的原理及区别

    一.当网络通信时采用TCP协议时:  1.过程: 第一步:(在真正的读写操作之前)Server 和Client 之间必须建立一个连接,连接的建立需要三次握手 经典的三次握手示意图: 第二步:进行读写操 ...

  9. [转载] TCP长连接与短连接的区别

    转载自http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html 1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前 ...

随机推荐

  1. pcre 不支持 utf 的问题

    问题: Error 500  preg_match(): Compilation failed: this version of PCRE is compiled without UTF suppor ...

  2. bzoj 2456: mode 思维题 好题

    题目描述: 给你一个 $n$ 个数的数列,其中某个数出现了超过 n div 2 次即众数,请你找出那个数.空间大小:1mb 题解:显然,我们是不能开任何数组的,此题专卡空间.然而我们要求的东西也十分简 ...

  3. [Codeforces 816A]Karen and Morning

    题目大意:给你一个时间(hh:mm),求最少经过多少分钟才能使这个时间变成回文. 解题思路:模拟,先判断0的情况,然后每过1分钟判断一次即可. C++ Code: #include<cstdio ...

  4. Linux Shell脚本编程-基础2

    命令退出状态码  bash每个命令,执行状态都有返回值 0表示成功 非0表示失败(1-255) $?特殊变量可以打印出上一条命令的状态返回值 脚本的状态返回值是脚本执行的最后一条命令 自定义脚本状态返 ...

  5. Python 批处理文本文件、进行查找

    去年换了一部手机,老手机终于光荣退休了,但是里面的便签里还存有很多文字记录,这个手机还不能备份到云,只能将每个便签保留为一个个的文本文件,我想要把所有的文本文件归到一个文本文件中,手动操作太麻烦了,刚 ...

  6. 紫书 习题 10-12 UVa 557(概率计算)

    开始的时候我没有考虑1/2的概率,直接一波组合数,然后WA 后来去看题解发现我们可以反过来想,求最后两个人不一样的情况 这个时候肯定会抛到最后的 所以每一种可能就是(0.5)^(n - 2),然后一共 ...

  7. C# Expression 树转化为SQL与语句(二)--解决参数问题

    在用Expression解析的的时候碰到一些参数(不是具体的值),会出现这种情况. 在这里我们希望得到的是id=10,而不是id=m_id;那如何来解析这些参数? ================== ...

  8. PIO Core

    PIO核概述 具有Avalon接口的并行输入/输出(parallel input/output - PIO)核,在Avalon存储器映射(Avalon Memory-Mapped Avalon-MM) ...

  9. caioj1442:第k小的数Ⅱ

    [传送门:caioj1442] 简要题意: 给出n个点,每个点都有一个权值,m个操作,操作有两种:第一种是询问l到r的第k小的值,然后输出这个值,第二种是将第x个点的值改为k 题解: 又是一道主席树的 ...

  10. json的键为变量而不是字符串时,怎么写?

    看栗子 /* 首先你创建了一个window的属性叫b, 并给它赋值为'cccddd' * 然后你创建了一个对象"a", 声明了一个它的属性叫b, 并且给b赋值为6 * 注意第一行的 ...