private Codec2 codec; private int connectTimeout; public AbstractEndpoint(URL url, ChannelHandler handler) { //调用父类 super(url, handler); //根据URL中的codec参数值,确定此处具体的Codec2实现类 this.codec = getChannelCodec(url); //设置connectTimeout this.connectTimeout = url.getPositiveParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT); } protected static Codec2 getChannelCodec(URL url) { //获取URL协议 String codecName = url.getProtocol(); //判断有没有该扩展名 if (ExtensionLoader.getExtensionLoader(Codec2.class).hasExtension(codecName)) { //通过ExtensionLoader加载具体实现类 return ExtensionLoader.getExtensionLoader(Codec2.class).getExtension(codecName); } else { //没有匹配到从扩展类进行加载 return new CodecAdapter(ExtensionLoader.getExtensionLoader(Codec.class) .getExtension(codecName)); } }此外该接口实现Resetable接口,该接口内部只有一个reset方法,该方法通过获取URL参数信息,重置了connectTimeout的信息以及Codec2的信息 。
AbstractServerAbstractServer是对服务端的抽象,该抽象类实现AbstractEndpoint和RemotingServer,该抽象类内部有五个核心属性,localAddress、bindAddress这两个属性都是在URL参数中获取,表示Server本地的地址以及绑定的地址 , 默认两个值是一致的,accepts表示是Server最大的连接次数,默认是0,表述没有限制,executorRepository、executor线程池相关的属性,executorRepository负责管理线程池,executor表示当前服务管理的线程池 。
//当前服务关联的线程池 ExecutorService executor; //本机地址 private InetSocketAddress localAddress; //绑定地址 private InetSocketAddress bindAddress; //最大连接数 private int accepts; //管理线程池 private ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();AbstractServer初始化也就是在构造函数中完成初始化的,然后通过调用其抽象方法doOpen实现启动服务器 。
public AbstractServer(URL url, ChannelHandler handler) throws RemotingException { //调用父类 super(url, handler); //从URL获取本地地址 localAddress = getUrl().toInetSocketAddress(); String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost()); int bindPort = getUrl().getParameter(Constants.BIND_PORT_KEY, getUrl().getPort()); if (url.getParameter(ANYHOST_KEY, false) || NetUtils.isInvalidLocalHost(bindIp)) { bindIp = ANYHOST_VALUE; } //绑定地址 bindAddress = new InetSocketAddress(bindIp, bindPort); //连接数 this.accepts = url.getParameter(ACCEPTS_KEY, DEFAULT_ACCEPTS); try { //调用该抽象方法启动服务 doOpen(); if (logger.isInfoEnabled()) { logger.info("Start " + getClass().getSimpleName() + " bind " + getBindAddress() + ", export " + getLocalAddress()); } } catch (Throwable t) { throw new RemotingException(url.toInetSocketAddress(), null, "Failed to bind " + getClass().getSimpleName() + " on " + getLocalAddress() + ", cause: " + t.getMessage(), t); } //创建该服务对应的线程池 executor = executorRepository.createExecutorIfAbsent(url); }
推荐阅读
- 驱动开发:内核封装WSK网络通信接口
- 二 Linux进程间通信
- 一 Linux进程间通信
- VS Code For Web 深入浅出 -- 进程间通信篇
- 聊聊Linux中CPU上下文切换
- 聊聊Vim的工作原理
- 驱动开发:通过Async反向与内核通信
- 今天聊聊跑步配速那些事 跑步机配速对照表
- 51单片机下实现软件模拟IIC通信
- 驱动通信:通过PIPE管道与内核层通信