Netty学习笔记(二) 实现服务端和客户端
在Netty学习笔记(一) 实现DISCARD服务中,我们使用Netty和Python实现了简单的丢弃DISCARD服务,这篇,我们使用Netty实现服务端和客户端交互的需求。
前置工作
开发环境
- JDK8
- Netty版本:5.0.0.Alpha2
- 集成环境:IDEA
- 构建工具:Gradle
依赖
compile group: 'io.netty', name: 'netty-all', version: '5.0.0.Alpha2'
compile group: 'org.projectlombok', name: 'lombok', version: '1.18.0'
服务端
Netty服务器主要由两部分组成:
- 配置服务器功能,如线程、端口
- 实现服务器处理程序
服务端HandleAdapter
我们是首先实现服务端处理程序,实现Handle要求继承HandleAdapter,这里我们继承SimpleChannelInboundHandler<T>,下面是具体实现的代码信息,其每个函数的作用,我们只需要重写我们所需要的方法即可。
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* Netty 服务Handle
*
* @author tao
*/
@ChannelHandler.Sharable
public class EchoServiceHandle extends SimpleChannelInboundHandler<String> {
/**
* 接收到新的消息
* @param ctx
* @param msg
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 打印接收到的消息
System.out.println("Netty服务端接收到消息 " + msg);
// 回复消息
ctx.channel().writeAndFlush("Send ----> 客户端" + ctx.channel().id() + "你好,我已经接收到你发送的消息");
}
/**
* 有新的连接加入
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("接入新的Channel,id = " + ctx.channel().id());
}
/**
* 服务端发生异常信息的时候
* @param ctx
* @param cause
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// 服务端发生异常
System.out.println("Netty 服务端发生异常 ,异常信息:" + cause);
ctx.close();
}
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) {}
}
服务端启动
在服务端的EchoServiceHandle完成之后,我们需要配置服务器的参数信息,比如端口等
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.Data;
/**
* @author tao
*/
@Data
public class EchoService {
private int port;
public void start() throws Exception {
EventLoopGroup boosGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap
.group(boosGroup, workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childHandler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//字符串解码器
pipeline.addLast(new StringDecoder());
//字符串编码器
pipeline.addLast(new StringEncoder());
//服务端处理器
pipeline.addLast(new EchoServiceHandle());
}
});
ChannelFuture sync = bootstrap.bind(port).sync();
System.out.println("Netty Service start with " + port + "...");
sync.channel().closeFuture().sync();
} finally {
workGroup.shutdownGracefully();
boosGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
EchoService service = new EchoService();
service.setPort(8080);
service.start();
}
}
启动后,我们可以看到启动信息如下:
Netty Service start with 8080...
客户端
客户端和服务端类似,可以相互参考学习.
客户端HandleAdapter
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
@ChannelHandler.Sharable
public class EchoClientHandle extends SimpleChannelInboundHandler<String> {
/**
* 连接创建成功的时候
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
//连接成功后向服务端发送问候消息
ctx.channel().writeAndFlush(Unpooled.copiedBuffer("你好,这里是Netty客户端", CharsetUtil.UTF_8));
}
/**
* 发生异常
* @param ctx
* @param cause
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println("exceptionCaught");
cause.printStackTrace();
ctx.close();
}
/**
* 接收到服务端发过来的数据
* @param ctx
* @param msg
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
//打印接收到的数据信息
System.out.println("channelRead = " + msg);
}
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) {}
}
客户端启动
import io.netty.bootstrap.Bootstrap;
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.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
/** @author tao */
@Data
@Accessors(chain = true)
@Slf4j
public class EchoClient {
private int port;
private String host;
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap
.group(group)
.channel(NioSocketChannel.class)
.handler(
new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 字符串解码器
pipeline.addLast(new StringDecoder());
// 字符串编码器
pipeline.addLast(new StringEncoder());
pipeline.addLast(new EchoClientHandle());
}
});
ChannelFuture sync = bootstrap.connect(new InetSocketAddress(host, port)).sync();
sync.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
EchoClient client = new EchoClient();
client.setHost("127.0.0.1").setPort(8080);
client.start();
}
}
效果
服务端效果
Netty Service start with 8080...
接入新的Channel,id = c0d4f037
Netty服务端接收到消息 你好,这里是Netty客户端
客户端效果
channelActive
channelRead = Send ----> 客户端c0d4f037你好,我已经接收到你发送的消息
Netty学习笔记(二) 实现服务端和客户端的更多相关文章
- 红帽学习笔记[RHCE]OpenLDAP 服务端与客户端配置
目录 OpenLDAP 服务端与客户端配置 关于LDIF 一个LDIF基本结构一个条目 属性 Object的类型 服务端 安装 生成证书 生成默认数据 修改基本的配置 导入基础数据 关于ldif的格式 ...
- Netty学习笔记(二)——netty组件及其用法
1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...
- 《精通并发与Netty》学习笔记(02 - 服务端程序编写)
上节我们介绍了开发netty项目所必需的开发环境及工具的使用,这节我们来写第一个netty项目 开发步骤 第一步:打开https://search.maven.org 找到netty依赖库 第二步:打 ...
- Netty学习笔记(二)
只是代码,建议配合http://ifeve.com/netty5-user-guide/此网站观看 package com.demo.netty; import org.junit.Before;im ...
- Kafka学习笔记2--Kafka的服务端配置
下载解压 kafka 后,在 kafka/config 下有 3 个配置文件与主题的生产.消费相关. server.properties--服务端配置 producer.properties--生产端 ...
- dubbo学习笔记二(服务调用)
项目结构 代码示例 由于之前的IEchoService 的一个方法只是在服务端控制台打印,不便在浏览器测试,所以新添加的方法 api和服务端代码变更 public interface IEchoSer ...
- SVN1.6服务端和客户端安装配置指导
本节向大家描述SVN1.6服务端和客户端安装配置步骤,随着SVN的快速发展,版本也进行了升级更新,本节就和大家一起学习一下SVN1.6服务端和客户端安装配置步骤,欢迎大家一起来学习.下面是具体介绍.1 ...
- Netty 学习(二):服务端与客户端通信
Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...
- Netty 学习(一):服务端启动 & 客户端启动
Netty 学习(一):服务端启动 & 客户端启动 作者: Grey 原文地址: 博客园:Netty 学习(一):服务端启动 & 客户端启动 CSDN:Netty 学习(一):服务端启 ...
随机推荐
- [Swift]LeetCode103. 二叉树的锯齿形层次遍历 | Binary Tree Zigzag Level Order Traversal
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...
- TCP/IP 详解常用术语
业务需要,最近看TCP/IP 这本书,专业名词太多了,总结一下,给后来着参考,直接使用. 后续会在读书时慢慢添加. ACK:(ACKnowledgment)TCP首部中的确认标志. ARP:地址解析协 ...
- Redis 设计与实现 (六)--发布订阅
发布订阅 相关命令:publish(发布) subscribe(订阅) psubscribe(支持通配符匹配) 发布者--频道--订阅者(发布和订阅都是客户端频道是服务端) 1.publish- ...
- python 模拟豆瓣登录(豆瓣6.0)
最近在学习python爬虫,看到网上有很多关于模拟豆瓣登录的例子,随意找了一个试了下,发现不能运行,对比了一下代码和豆瓣网站,发现原来是豆瓣网站做了修改,增加了反爬措施. 首先看下要模拟登录的网站: ...
- arm-none-eabi-gcc编译报错:exit.c:(.text.exit+0x16): undefined reference to `_exit'
该问题的出现是链接文件导致的,是不同的gcc交叉编译器支持的链接文件不同造成的,有几种方法可以解决这个问题. 方法一:更换arm-none-eabi-gcc的版本,这个一般是新的gcc编译器才会抱着错 ...
- 专访 | 新浪架构师:0-5年Java工程师的职业规划如何做?
经历了2018年末的阵痛,大家都积攒着一股暗劲蠢蠢欲动. 3月初即将迎来2019年互联网行业换工作的大潮,技术工程师的升级换位对于一家互联网公司来说无疑是命脉般的存在——技术强则公司强! 如何做一个抢 ...
- Netty浅析
Netty是JBoss出品的高效的Java NIO开发框架,关于其使用,可参考我的另一篇文章 netty使用初步.本文将主要分析Netty实现方面的东西,由于精力有限,本人并没有对其源码做了极细致的研 ...
- 【java设计模式】(6)---迭代器模式(案例解析)
设计模式之迭代器模式 一.java迭代器介绍 1.迭代器接口 在jdk中,与迭代器相关的接口有两个:Iterator 与 Iterable. Iterator:迭代器,Iterator及其子类通常是迭 ...
- MongoDB exception:connection failed
根据http://www.runoob.com/mongodb/mongodb-window-install.html的教程配置了MongoDB,Mongod.exe配置为 --port 指令表明mo ...
- 【朝花夕拾】Android性能篇之(五)Android虚拟机
前言 Android虚拟机的使用,使得android应用和Linux内核分离,这样做使得android系统更稳定可靠,比如程序中即使包含恶意代码,也不会直接影响系统文件:也提高了跨平台兼容性.在And ...