在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学习笔记(二) 实现服务端和客户端的更多相关文章

  1. 红帽学习笔记[RHCE]OpenLDAP 服务端与客户端配置

    目录 OpenLDAP 服务端与客户端配置 关于LDIF 一个LDIF基本结构一个条目 属性 Object的类型 服务端 安装 生成证书 生成默认数据 修改基本的配置 导入基础数据 关于ldif的格式 ...

  2. Netty学习笔记(二)——netty组件及其用法

    1.Netty是 一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端. 原生NIO存在的问题 1) NIO的类库和API繁杂,使用麻烦:需要熟练掌握Selector.Se ...

  3. 《精通并发与Netty》学习笔记(02 - 服务端程序编写)

    上节我们介绍了开发netty项目所必需的开发环境及工具的使用,这节我们来写第一个netty项目 开发步骤 第一步:打开https://search.maven.org 找到netty依赖库 第二步:打 ...

  4. Netty学习笔记(二)

    只是代码,建议配合http://ifeve.com/netty5-user-guide/此网站观看 package com.demo.netty; import org.junit.Before;im ...

  5. Kafka学习笔记2--Kafka的服务端配置

    下载解压 kafka 后,在 kafka/config 下有 3 个配置文件与主题的生产.消费相关. server.properties--服务端配置 producer.properties--生产端 ...

  6. dubbo学习笔记二(服务调用)

    项目结构 代码示例 由于之前的IEchoService 的一个方法只是在服务端控制台打印,不便在浏览器测试,所以新添加的方法 api和服务端代码变更 public interface IEchoSer ...

  7. SVN1.6服务端和客户端安装配置指导

    本节向大家描述SVN1.6服务端和客户端安装配置步骤,随着SVN的快速发展,版本也进行了升级更新,本节就和大家一起学习一下SVN1.6服务端和客户端安装配置步骤,欢迎大家一起来学习.下面是具体介绍.1 ...

  8. Netty 学习(二):服务端与客户端通信

    Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...

  9. Netty 学习(一):服务端启动 & 客户端启动

    Netty 学习(一):服务端启动 & 客户端启动 作者: Grey 原文地址: 博客园:Netty 学习(一):服务端启动 & 客户端启动 CSDN:Netty 学习(一):服务端启 ...

随机推荐

  1. Hello,Thread

    创建线程的三种方法,线程的生命周期,sleep,yield,join,wait 和notify,线程组,守护线程,线程的优先级 ◆ 如何创建线程 ◆ Java 中创建线程的方法有三种: 继承 Thre ...

  2. [Swift]LeetCode26. 删除排序数组中的重复项 | Remove Duplicates from Sorted Array

    Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...

  3. [Swift]LeetCode113. 路径总和 II | Path Sum II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  4. [Swift]LeetCode981. 基于时间的键值存储 | Time Based Key-Value Store

    Create a timebased key-value store class TimeMap, that supports two operations. 1. set(string key, s ...

  5. 【jQuery】(1)---初次接触Jquery

    1.浅理解Jquery:jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents.events.实现动画效果,并且方便地为网站提供AJAX交互. 2.D ...

  6. docker commit命令创建新的镜像

    docker commit命令创建新的镜像 1.运行容器 2.修改容器 3.将容器保存为新容器 (1)运行容器 [root@cmdb-server docker]# docker run -ti ce ...

  7. 为OPENCV添加freetype支持并显示中文字符(在mac上编译opencv及contrib库)

    在mac电脑上管理这些gnu的库一般都使用Homebrew,但总有一些你个性化的需要是官方的Homebrew配方无法满足的.比如在屏幕的输出中使用中文字符. 在OPENCV中输出UTF8字符集早已经有 ...

  8. Presto 常用配置及操作

    一.介绍 Presto是一个开源的分布式SQL查询引擎,适用于交互式分析查询,数据量支持GB到PB字节. Presto的设计和编写完全是为了解决像Facebook这样规模的商业数据仓库的交互式分析和处 ...

  9. Jexus~Linux环境下的部署

    Jexus 即 Jexus Web Server,简称JWS,是Linux平台上的一款ASP.NET WEB服务器,是 Linux.Unix.FreeBSD 等非Windows系统架设 ASP.NET ...

  10. 初学Java Web(6)——JSP学习总结

    为什么要学习 JSP Servlet 的短板: Servlet 的出现,是为了解决动态输出网页的问题. 虽然这样做目的能达到,但是存在一些缺陷: 在 Servlet 输出网页片段非常恶心 (可读性差, ...