第一步的任务是实现一个基本骨架, 让程序能够跑起来。
程序能够监听一个指定的端口接收客户端端连接,并在控制台打印出客户端发送过来的字符串。
启动代码
服务端启动代码如下:(是不是跟netty的启动代码很相似?)
ChannelHandler handler = (o) -> { |
以上的测试监听了6666端口,并将接收到的文本消息打印到控制台
实现思路
这一步的目标就是为了能让程序跑起来,因此错误处理,异步处理等等能不管的尽量不管,一切尽可能的简单。
主要实现的内容包括EventLoop和 Channel,以及一个自定义的ChannelHandler,为了便于理解, 总的的代码控制在300行左右。
接口定义
这里定义了EventLoopGroup, EventLoop, Channel, ChannelHandler四个接口,都非常非常的简单。public interface EventLoopGroup {
//获取组内的下一个EventLoop
EventLoop next();
//将channel注册到EventLoopGroup
void register(Channel channel);
}
public interface EventLoop extends EventLoopGroup {
// 纯粹的概念定义,方法全部继承自EventLoopGroup
}
//我这里没有unsafe,所以把unsafe的功能整进Channel了
public interface Channel {
//将Channel注册到EventLoop
void register(EventLoop eventLoop);
//绑定指定端口
void bind(SocketAddress localAddress);
//处理事件
Object doReadMessages();
//获取关联的EventLoop
EventLoop eventLoop();
//这个方法是我为了简化代码自己发明的,netty中没有
void setHandler(ChannelHandler handler);
}
public interface ChannelHandler {
//没错,在我的实现里,ChannelHandler只有一个方法
void channelRead(Object msg);
}
实现NioEventLoopGroup
接着是实现NioEventLoopGroup,这个逻辑很简单,就是初始化指定数目的NioEventLoop,并实现一个选择算法
public class NioEventLoopGroup implements EventLoopGroup { |
实现NioEventLoop
下面是NioEventLoop,NioEventLoop的实现相对来说复杂一些,它负责创建选择器,以及进行select循环
public class NioEventLoop implements EventLoop, Runnable { |
实现AbstractNioChannel
接着就是要实现NioServerSocketChannel以及NioSocketChannel了,因为这两个类比较相似,为了避免重复代码,所以提取了一个抽象基类AbstractNioChannel
//AbstractNioChannel负责NioServerSocketChannel以及NioSocketChannel的公共操作 |
实现NioServerSocketChannel
NioServerSocketChannel实际上就是Nio的ServerSocketChannel的封装,主要负责监听端口,接受连接
//负责监听端口,接受连接 |
实现NioSocketChannel
NioSocketChannel实际上就是Nio的SocketChannel的封装,主要负责接收数据
public class NioSocketChannel extends AbstractNioChannel{ |
实现ServerBootstrap
最后要实现的就是启动器ServerBootstrap了,这个类的主要工作就是负责组装以上实现的内容
//服务端启动器 |
阶段一总结
到此为止,这个极度缩水版的netty的骨架已经完成了,在netty中,bind和accept都是在Channel的pipeline中完成的,但我这个实现并没有pipeline,所以直接放在的Channel中,以后的更新中我会把这些特性都加入进来。