本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本文记录使用Netty简单实现服务端和客户端
Netty简单介绍
摘自官网介绍:
Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server. ‘Quick and easy’ doesn’t mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise. 翻译: Netty 是一个 NIO 客户端服务器框架,它可以快速轻松地开发网络应用程序,例如协议服务器和客户端。 它极大地简化和精简了 TCP 和 UDP 套接字服务器等网络编程。 “快速而简单”并不意味着生成的应用程序会受到可维护性或性能问题的影响。 Netty 是根据从许多协议(例如 FTP、SMTP、HTTP 以及各种基于二进制和文本的遗留协议)的实现中获得的经验而精心设计的。 结果,Netty 成功地找到了一种方法,可以在不妥协的情况下实现易于开发、性能、稳定性和灵活性。
前期准备
maven引入io.netty
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.63.Final</version>
</dependency>
服务端代码
package com.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
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 java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args) {
//定义工作组
EventLoopGroup bossGroup = new NioEventLoopGroup();
//workGroup配置2个线程
EventLoopGroup workGroup = new NioEventLoopGroup(2);
ChannelFuture future = new ServerBootstrap()
//bossGroup分发请求给workGroup:bossGroup负责监听端口请求,workGroup负责处理请求(读写)
.group(bossGroup, workGroup)
设置通道channel,NioServerSocketChannel用于服务端非阻塞地接收TCP连接
.channel(NioServerSocketChannel.class)
//添加handler,管道中的处理器,通过ChannelInitializer来构造
.childHandler(new ChannelInitializer<SocketChannel>() {
//此方法每次客户端连接都会调用,是为通道初始化的方法
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println(Thread.currentThread().getName()+"收到请求...");
ch.pipeline().addLast(new StringDecoder(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
System.out.println(Thread.currentThread().getName()+"接收到的消息: "+byteBuf.toString(StandardCharsets.UTF_8));
}
});
}
})
//绑定监听端口
.bind(8888);
try {
//同步
future.sync();
//监听关闭
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
客户端代码
package com.netty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
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.StringEncoder;
import java.net.InetSocketAddress;
public class Client {
public static void main(String[] args) {
try {
Channel channel = new Bootstrap()
.group(new NioEventLoopGroup())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder());
}
})
.connect(new InetSocketAddress("localhost", 8888))
.sync().channel();
System.out.println(channel);
channel.writeAndFlush("Hello, server");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试
1.启动服务端
2.启动客户端
客户端1:
服务端:
3.再启动一个客户端
客户端2:
服务端: