注:本文适合对象需对java NIO API的使用及异步事件模型(Reactor模式)有一定程度的了解,主要讲述使用java原生NIO实现一个TCP监听绑定的过程及细节设计。

我们一开始设计了一个TCP接入服务类,这个类提供了一个API方法提供对本地一系列地址(端口)的监听绑定,类初始化后完成Selector的open操作如下:

selector = Selector.open();

提供的绑定API,其方法签名如下:

 /*** Binds to the specified local addresses and start to accept incoming connections. If any address binding failed then* rollback the already binding addresses. Bind is fail fast, if encounter the first bind exception then throw it immediately.* * @param firstLocalAddress* @param otherLocalAddresses* @throws throw if bind failed.*/synchronized public void bind(SocketAddress firstLocalAddress, SocketAddress... otherLocalAddresses) throws IOException;

为何需要同步?因为我们不希望多个线程同时调用该方法,导致地址绑定异常。

参数中可以传递多个本地地址(端口)同时进行监听绑定。

在NIO的绑定过程中需进行事件注册(对OP_ACCEPT感兴趣),如下:

  ServerSocketChannel ssc = ServerSocketChannel.open();ssc.configureBlocking(false);ServerSocket ss = ssc.socket();ss.setReuseAddress(config.isReuseAddress());ss.bind(address, config.getBacklog());ssc.register(selector, SelectionKey.OP_ACCEPT);

由于注册过程中除了涉及锁竞争还可能产生死锁,所以一般的做法都是将绑定地址放在队列中进行异步注册由reactor线程进行处理,例如:

  bindAddresses.addAll(localAddresses);if (!bindAddresses.isEmpty()) {synchronized (lock) {// wake up for unblocking the select() to process binding addressesselector.wakeup();// wait for bind resultwait0();}}

从同步注册变为异步注册后就存在一个问题,实际注册绑定时可能存在端口已绑定的异常,在异步情况下就需要线程间通信来通知异常消息,并向调用方反馈。

如上面代码片段中的wait0()方法就是等待绑定结果,若出现绑定异常则抛出

  private void wait0() throws IOException {while (!this.endFlag) {try {lock.wait();} catch (InterruptedException e) {throw new IOException(e);}}// reset end flagthis.endFlag = false;if (this.exception != null) {IOException e = exception;this.exception = null;throw e;}}

以上代码也说明了,NIO异步模型转化为同步API导致的模型阻抗付出了额外的代价和开销 --- 线程间通信。 至此,完成了TCP服务监听过程,下文将进一步讲述服务接入和数据传输相关设计细节。

踏莎行·术 - NIO系列2:TCP监听绑定相关推荐

  1. 踏莎行·术 - NIO系列4:TCP服务数据读写

    注:本文适合对象需对java NIO API的使用及异步事件模型(Reactor模式)有一定程度的了解,主要讲述使用java原生NIO实现一个TCP服务的过程及细节设计. 上文讲到当客户端完成与服务端 ...

  2. 踏莎行·术 - NIO系列3:TCP服务接入

    注:本文适合对象需对java NIO API的使用及异步事件模型(Reactor模式)有一定程度的了解,主要讲述使用java原生NIO实现一个TCP服务的过程及细节设计. 前文讲述了NIO TCP服务 ...

  3. 踏莎行·术 - NIO系列1:框架拆解

    最近一年用NIO写了不少网络程序,也研究了一些开源NIO网络框架netty.mina等,总结了一下NIO的架构特点. 无论是netty还是mina它们都在java原生NIO的基础上进行了完善的封装,虽 ...

  4. 踏莎行·术 - NIO系列5:事件模型

    前文讲述了NIO数据读写处理,那么这些数据最终如何被递交给上层业务程序进行处理的呢? NIO框架一般都采用了事件派发模型来与业务处理器交互,它与原生NIO的事件机制是模型匹配的,缺点是带来了业务处理的 ...

  5. zabbix自动发现规则实现批量监控主机的TCP监听端口

    检查服务器所有监听端口和其对应的服务名称的脚本可以参考https://blog.zzyyxx.top/blog/post/gordy/acf57f04f9e1  现在准备加入zabbix自动发现规则并 ...

  6. python 监听tcp端口_创建TCP监听_创建TCP监听_功能示例_Python SDK示例_SDK 参考_开发指南_负载均衡 - 阿里云...

    # encoding=utf-8 import json import sys # 调用AcsClient参数进行身份验证 from aliyunsdkcore.client import AcsCl ...

  7. linux 内核参数somaxconn TCP监听队列长度

    在Linux中,/proc/sys/net/core/somaxconn这个参数,linux中内核的一个不错的参数somaxconn. 对于一个TCP连接,Server与Client需要通过三次握手来 ...

  8. java tcp 监听端口_【TCP/IP】端口未监听,还能访问成功?

    作者:Mr林_月生链接:https://www.jianshu.com/p/3ab10c8685b5 现象 直接上图 可以发现,本地没监听50000端口的服务,但是尝试连接本地50000端口时,却能成 ...

  9. centos7开启tcp6_centos中docker映射出来的端口被tcp6监听,而没有被tcp监听导致ip+端口无法进行访问...

    如图,我通过docker构建容器时,映射出来的端口是8081,但是通过ip+8081无法访问,在检查了一遍安全组规则是否开放,以及百度以后查到是由于端口被tcp6监听,没有被tcp监听到导致的. 按照 ...

最新文章

  1. 在分页状态下删除纪录的问题
  2. gis快速接地开关_一种基于扫描电镜和能谱仪的GIS放电异物来源分析方法
  3. 2018 年,去百度面试 Java 后端的一次面试经历
  4. 使用多级分组报表展现分类数据
  5. c++对象的动态建立和释放
  6. linux Figlet 转换字符字
  7. oracle 中的几天后,几年后
  8. 图说苹果工作站-MAC PRO
  9. SAP ABAP和C4C,Hybris Commerce里一些性能分析工具
  10. 在Ubuntu|CentOS上安装Shutter截图工具及快捷键设置
  11. 前端学习(2267)vue造轮子之添加icon
  12. fetch oracle 12c下载,十二、Oracle Fetch子句
  13. 在线批量身份证识别系统
  14. header标签为什么不能改变背景颜色呢?
  15. UWP 手绘视频创作工具技术分享系列 - 文字的解析和绘制
  16. 人工智能AI实训平台
  17. 明天终于要到公司开工了
  18. Docker - volume、-v 区别
  19. iloc和loc区别和应用总结
  20. PCB原理图绘制(7)——PCB的设置与布线

热门文章

  1. 集成zxing扫码解决二维码自动放大
  2. Final cut pro剪辑视频快捷键汇总
  3. Ubuntu18.04将Python升级到3.8
  4. vba excel 开发游戏_VBA代码助手专业版正式发布,让天下没有难写的VBA代码
  5. 本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
  6. matlab短均线滞后项,均线延迟的成因及解决
  7. 一个资深程序员看12306 (二)
  8. 手机贴膜利润超百倍 消费者为无用功能高价买单
  9. 《鬼灭之刃 无限列车编》超越《哈尔移动城堡》《哈利波特》成史上第五位
  10. 小米手环7、小米手环7pro和小米手环7/nfc的区别