码出高效:Java开发手册-第1章(5)

简介: 本书源于影响了全球250万名开发工程师的《阿里巴巴Java开发手册》,作者静心沉淀,对Java规约的来龙去脉进行了全面而彻底的内容梳理。本书以实战为中心,以新颖的角度全面阐述面向对象理论,逐步深入地探索怎样成为一位优秀开发工程师。比如:如何驾轻就熟地使用各类集合框架;如何得心应手地处理高并发多线程问题;如何顺其自然地写出可读性强、可维护性好的优雅代码。 本书旁征博引、文风轻松,秉持“图胜于表,表胜于言”的理念,深入浅出地将计算机基础、面向对象思想、JVM探源、数据结构与集合、并发与多线程、单元测试等知识客观、立体地呈现出来。紧扣学以致用......

1.5.3 TCP 建立连接

      传输控制协议(Transmission Control Protocol,TCP),是一种面向连接、确保数据在端到端间可靠传输的协议。面向连接是指在发送数据前,需要先建立一条虚拟的链路,然后让数据在这条链路上“流动”完成传输。为了确保数据的可靠传输,不仅需要对发出的每一个字节进行编号确认,校验每一个数据包的有效性,在出现超时情况时进行重传,还需要通过实现滑动窗口和拥塞控制等机制,避免网络状况恶化而最终影响数据传输的极端情形。每个TCP 数据包是封装在IP 包中的,每一个IP 头的后面紧接着的是TCP 头,TCP 报文格式如图1-17 所示。

17.jpg

图1-17 TCP 报文格式

      协议第一行的两个端口号各占两个字节,分别表示了源机器和目标机器的端口号。这两个端口号与IP 报头中的源IP 地址和目标IP 地址所组成的四元组可唯一标识一条TCP 连接。由于TCP 是面向连接的,因此有服务端和客户端之分。需要服务端先在相应的端口上进行监听,准备好接收客户端发起的建立连接请求。当客户端发起第一个请求建立连接的TCP 包时,目标机器端口就是服务端所监听的端口号。比如广为人知的端口号——HTTP 服务的80 端口、HTTPS 服务的443 端口、SSH 服务的22 端口等。可通过netstat 命令列出机器上已建立的连接信息,其中包含唯一标识一条连接的四元组,以及各连接的状态等内容,如图1-18 所示,图中的红框代表端口号。

18.jpg

图1-18 IP 地址与端口信息

      协议第二行和第三行是序列号,各占4 个字节。前者是指所发送数据包中数据部分第一个字节的序号,后者是指期望收到来自对方的下一个数据包中数据部分第一个字节的序号。

      由于TCP 报头中存在一些扩展字段,所以需要通过长度为4 个bit 的头部长度字段表示TCP 报头的大小,这样接收方才能准确地计算出包中数据部分的开始位置。TCP 的FLAG 位由6 个bit 组成, 分别代表SYN、ACK、FIN、URG、PSH、RST,都以置1 表示有效。我们重点关注SYN、ACK 和FIN。SYN(Synchronize Sequence Numbers)用作建立连接时的同步信号;ACK(Acknowledgement)用于对收到的数据进行确认,所确认的数据由确认序列号表示;FIN(Finish)表示后面没有数据需要发送,通常意味着所建立的连接需要关闭了。

      TCP 报头中的其他字段可以阅读RFC793 来掌握,本书在此不加赘述。接下来重点分析TCP 中连接建立的原理。图1-19 展示了正常情形下通过三次握手建立连接的过程。A 与B 的机器标识并不是绝对意义上的服务器与客户端。发起请求的也可能是服务器,向另一台其他后端服务器发送TCP 连接请求。前者需要在后者发起连接建立请求时先打开某个端口等待数据传输,否则将无法正常建立连接。三次握手指的是建立连接的三个步骤:

  • A 机器发出一个数据包并将SYN 置 1,表示希望建立连接。这个包中的序列号假设是x 。
  • B 机器收到 A 机器发过来的数据包后,通过 SYN 得知这是一个建立连接的请求,于是发送一个响应包并将SYN 和ACK 标记都置1。假设这个包中的序列号是y ,而确认序列号必须是x +1,表示收到了A 发过来的SYN。在TCP 中,SYN 被当作数据部分的一个字节。
  • A 收到 B 的响应包后需进行确认,确认包中将 ACK 置 1,并将确认序列号设置为y +1,表示收到了来自B 的SYN。

19.jpg

图1-19 TCP 三次握手创建连接

      这里为什么需要第3 次握手?它有两个主要目的:信息对等和防止超时。先从信息对等角度来看,如表1-8 所示,双方只有确定4 类信息,才能建立连接。在第2 次握手后,从B 机器视角看还有两个红色的NO 信息无法确认。在第3 次握手后,B 机器才能确认自己的发报能力和对方的收报能力是正常的。

表1-8 TCP 三次握手待确认信息20.jpg

      连接三次握手也是防止出现请求超时导致脏连接。TTL 网络报文的生存时间往往都会超过TCP 请求超时时间,如果两次握手就可以创建连接,传输数据并释放连接后,第一个超时的连接请求才到达B 机器的话,B 机器会以为是A 创建新连接的请求,然后确认同意创建连接。因为A 机器的状态不是SYN_SENT,所以直接丢弃了B 的确认数据,以致最后只是B 机器单方面创建连接完毕,简要示意图如图1-20所示。

21.jpg

图1-20 两次握手导致的TCP 脏连接

      如果是三次握手,则B 机器收到连接请求后,同样会向A机器确认同意创建连接,但因为A 机器不是SYN_SENT 状态,所以会直接丢弃,B 机器由于长时间没有收到确认信息,最终超时导致连接创建失败,因而不会出现脏连接。根据抓包分析,呈现出三次握手请求过程,SYN+ACK 的应答,告诉A 机器期望下一个数据包的第一个字节序号为1,如图1-21 所示。

22.jpg

图1-21 TCP 三次握手抓包分析

      从编程的角度,TCP 连接的建立是通过文件描述符(File Descriptor,fd)完成的。通过创建套接字获得一个fd,然后服务端和客户端需要基于所获得的fd 调用不同的函数分别进入监听状态和发起连接请求。由于fd 的数量将决定服务端进程所能建立连接的数量,对于大规模分布式服务来说,当fd 不足时就会出现“open too many files”错误而使得无法建立更多的连接。为此,需要注意调整服务端进程和操作系统所支持的最大文件句柄数。通过使用ulimit -n 命令来查看单个进程可以打开文件句柄的数量。如果想查看当前系统各个进程产生了多少句柄,可以使用如下的命令:

lsof -n | awk '{print $2}'| sort|uniq -c |sort -nr|more

      执行结果如图1-22 所示,左侧列是句柄数,右侧列是进程号。lsof 命令用于查看当前系统所打开fd 的数量。在Linux 系统中,很多资源都是以fd 的形式进行读写的,除了提到的文件和TCP 连接,UDP 数据报、输入输出设备等都被抽象成了fd。

23.jpg

图1-22 文件句柄与进程ID 的对应关系

      想知道具体的PID 对应的具体应用程序是谁,使用如下命令即可:

ps -ax|grep 32764

      Java 进程示例如图1-23 所示。

24.jpg

图1-23 根据进程ID 查询具体进程

      TCP 在协议层面支持Keep Alive 功能,即隔段时间通过向对方发送数据表示连接处于健康状态。不少服务将确保连接健康的行为放到了应用层,通过定期发送心跳包检查连接的健康度。一旦心跳包出现异常不仅会主动关闭连接,还会回收与连接相关的其他用于提供服务的资源,确保系统资源最大限度地被有效利用。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
打赏
0
0
0
0
28
分享
相关文章
|
4月前
|
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
620 10
一天成为Java开发高手:用飞算JavaAI实现十倍提效
“一天成为Java开发高手”曾被视为天方夜谭,但飞算JavaAI的出现改变了这一局面。这款AI开发助手通过智能引导、需求分析、自动化逻辑处理和完整代码工程生成,大幅简化了Java开发流程。它不仅帮助新手快速上手,还让资深开发者提高效率,减少调试时间。现在,参与“飞算JavaAI炫技赛”,展示你的开发实力,赢取丰厚奖品!
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
智慧产科一体化管理平台源码,基于Java,Vue,ElementUI技术开发,二开快捷
智慧产科一体化管理平台覆盖从备孕到产后42天的全流程管理,构建科室协同、医患沟通及智能设备互联平台。通过移动端扫码建卡、自助报道、智能采集数据等手段优化就诊流程,提升孕妇就诊体验,并实现高危孕产妇五色管理和孕妇学校三位一体化管理,全面提升妇幼健康宣教质量。
44 12
Java高级应用开发:基于AI的微服务架构优化与性能调优
在现代企业级应用开发中,微服务架构虽带来灵活性和可扩展性,但也增加了系统复杂性和性能瓶颈。本文探讨如何利用AI技术,特别是像DeepSeek这样的智能工具,优化Java微服务架构。AI通过智能分析系统运行数据,自动识别并解决性能瓶颈,优化服务拆分、通信方式及资源管理,实现高效性能调优,助力开发者设计更合理的微服务架构,迎接未来智能化开发的新时代。
菜鸟之路day02-04拼图小游戏开发一一JAVA基础综合项目
本项目基于黑马程序员教程,涵盖面向对象进阶、继承、多态等知识,历时约24小时完成。项目去除了登录和注册模块,专注于单机游戏体验。使用Git进行版本管理,代码托管于Gitee。项目包含窗体搭建、事件监听、图片加载与打乱、交互逻辑实现、菜单功能及美化界面等内容。通过此项目,巩固了Java基础并提升了实际开发能力。 仓库地址:[https://gitee.com/zhang-tenglan/puzzlegame.git](https://gitee.com/zhang-tenglan/puzzlegame.git)
46 6
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
47 5
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
69 2

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等