上节我们编写了netty服务端的程序,这节我们来写客户端程序

第一步:改造服务端程序为:

(1)MyServer类:

package com.ssy.netty.demo01;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; /**
* netty作为长连接的服务器基于websoket,实现客户端与服务器端长连接。
*/
public class MyServer {
public static void main(String[] args) {
//负责接收客户端连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
//处理连接
EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup) // 绑定线程池
.channel(NioServerSocketChannel.class)
.childHandler(new MyServerInitializer()); //绑定端口号
ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

(2)MyServerInitializer类

package com.ssy.netty.demo01;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; /**
* 绑定客户端连接时候触发操作
*/
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
//负载http 请求编码解码
//pipeline.addLast("httpServerCodec",new HttpServerCodec());
//实际处理请求
//pipeline.addLast("httpServerHandler",new HttpServerHandler());
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
pipeline.addLast(new LengthFieldPrepender(4));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast(new MyServerHandler());
}
}

(3)MyServerHandler类

package com.ssy.netty.demo01;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import java.time.LocalDateTime; public class MyServerHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(ctx.channel().remoteAddress());
System.out.println("client output:"+msg);
ctx.writeAndFlush("from server:" + LocalDateTime.now());
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

编写客户端主程序MyClient

package com.ssy.netty.demo01;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel; public class MyClient {
public static void main(String[] args) {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup) // 绑定线程池
.channel(NioSocketChannel.class)
.handler(new MyClientInitializer()); //绑定端口号
ChannelFuture channelFuture = bootstrap.connect("localhost",8888).sync();
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
eventLoopGroup.shutdownGracefully();
}
}
}

第二步:编写MyClientInitializer

package com.ssy.netty.demo01;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
pipeline.addLast(new LengthFieldPrepender(4));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast(new MyClientHandler());
}
}

第三步:编写MyClientHandler

package com.ssy.netty.demo01;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import java.time.LocalDateTime; public class MyClientHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(ctx.channel().remoteAddress());
System.out.println("client output:"+msg);
ctx.writeAndFlush("from client:" + LocalDateTime.now());
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush("来自客户端的问候");
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}

分别启动MyServer程序和MyClient程序,客户端成功调用服务端。

到此为止,我们已经完成了简单的netty服务端与客户端的通信程序,下节我们会对谷歌的Google Protobuf做一次详解,敬请期待吧!

《精通并发与Netty》学习笔记(03 - 客户端程序编写)的更多相关文章

  1. 《精通并发与Netty》学习笔记(01 - netty介绍及环境搭建)

    一.Netty介绍     Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.     ...

  2. Netty学习笔记(二) 实现服务端和客户端

    在Netty学习笔记(一) 实现DISCARD服务中,我们使用Netty和Python实现了简单的丢弃DISCARD服务,这篇,我们使用Netty实现服务端和客户端交互的需求. 前置工作 开发环境 J ...

  3. Netty学习笔记-入门版

    目录 Netty学习笔记 前言 什么是Netty IO基础 概念说明 IO简单介绍 用户空间与内核空间 进程(Process) 线程(thread) 程序和进程 进程切换 进程阻塞 文件描述符 文件句 ...

  4. Netty 学习笔记(1)通信原理

    前言 本文主要从 select 和 epoll 系统调用入手,来打开 Netty 的大门,从认识 Netty 的基础原理 —— I/O 多路复用模型开始.   Netty 的通信原理 Netty 底层 ...

  5. Mina框架的学习笔记——Android客户端的实现

    Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...

  6. 精通并发与 Netty (一)如何使用

    精通并发与 Netty Netty 是一个异步的,事件驱动的网络通信框架,用于高性能的基于协议的客户端和服务端的开发. 异步指的是会立即返回,并不知道到底发送过去没有,成功没有,一般都会使用监听器来监 ...

  7. Redis:学习笔记-03

    Redis:学习笔记-03 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 7. Redis配置文件 启动 ...

  8. 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试

    机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...

  9. OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓

    本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...

随机推荐

  1. openstack使用

    管理员登陆: 身份管理--->创建项目 身份管理--->创建用户(角色:_member_)(管理指定项目) 管理员--->云主机类型--->创建云主机 管理员--->镜像 ...

  2. 【leetcode】1288. Remove Covered Intervals

    题目如下: Given a list of intervals, remove all intervals that are covered by another interval in the li ...

  3. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  4. 「BZOJ 2653」middle「主席树」「二分」

    题意 一个长度为\(n\)的序列\(a\),设其排过序之后为\(b\),其中位数定义为\(b[n/2]\),其中\(a,b\)从\(0\)开始标号,除法取下整.给你一个长度为\(n\)的序列\(s\) ...

  5. 什么是挂载?mount的用处在哪?

    关于挂载的作用一直不是很清楚,今天在阅读教材时看见了mount这个命令,发现它的用处很隐晦但非常强大.奈何教材说的不明朗,因此在网上整合了一些优秀的解释,看完之后豁然开朗. 1.提一句Windows下 ...

  6. SpringMVC 理论

    应用系统三层架构: C/S:客户端/服务器 B/S:浏览器/服务器 标准分层: 表现层:WEB 层,接受结果,响应结果,分发请求:通常客户端使用 http 协议请求 web 层,web 层需要接受 h ...

  7. golang中遍历汇总

    直接上例子: 例子1: package main import( "fmt" ) func main(){ a := map[string]string{ "alice& ...

  8. cassandra3.11.4集群搭建

    环境:[centos7.cassandra-3.11.4] 三个节点:[主机名为master,slave-1,slave-2, 用户均为root] 1.下载cassandra cassandra下载地 ...

  9. 终端和vim中文编码问题

    一. 终端中文显示乱码 有网友说修改 /var/lib/locales/supported.d/locale 和 /etc/default/locale 就可以了但是如果多人共用一台机器没有root权 ...

  10. shell脚本编程进阶

    在linux shell中,通常我们将一些命令写在一个文件中就算是一个shell脚本了,但是如果需要执行更为复杂的逻辑判断,我们就需要使用流程控制语句来支持了.所谓流程控制既是通过使用流程控制语句对程 ...