实战 | 服务端开发与计算机网络结合的完美案例

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 笔记

前言


大家好,我是阿秀

后端,可以说是仅次于算法岗之外竞争最为激烈的岗位,而其中的服务端开发也是很多人会选择在秋招中投递的一个岗位,我想对于很多人来说,走上服务端开发之路的起点就是一个回声服务器了。

今天带大家实战一把,真实体验服务端底层数据交换的点点滴滴,在这过程中可以让你看见 TCP 三次握手四次挥手的具体过程,全程干货,不开玩笑。


环境工具


客户端:Ubuntu 16.04 ,IP:192.168.78.128 ,简称为客户端A

服务端:Ubuntu 16.04 ,IP:192.168.78.130,简称为服务端B

抓包利器-大白鲨  Wireshark  以及 Linux 下的抓包命令 tcpdump

GCC:5.4.0

因为 Wireshark 的图标就很像一条大鲨鱼的鱼鳍,所以又叫大白鲨,不信你看看

大白鲨


三次握手与四次挥手


这里简单介绍下 TCP 最经典的三次握手与四次挥手

三次握手四次挥手

三次握手
  1. 第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为1,seq(Sequence Number) 为 x;然后,客户端进入 SYN_SEND 状态,等待服务端的确认;
  2. 第二次握手:服务端收到 SYN 报文段。服务端收到客户端的 SYN 报文段,需要对这个SYN 报文段进行确认,设置 ack(Acknowledgment Number) 为 x+1 (也就是 seq+1);同时,自己还要发送 SYN 请求信息,将 SYN 位置为1,seq 为 y;服务端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务端进入 SYN_RECV 的状态;
  3. 第三次握手:客户端收到服务端的 SYN+ACK 报文段。然后将ack设置为y+1,向服务端发送ACK报文段,这个报文段发送完毕以后,客户端和服务端端都进入 ESTABLISHED 状态,完成TCP三次握手。
数据交互

成功建立连接后,客户端与服务端就开始进行数据交互。客户端发送数据,服务端回复收到该数据,然后交替进行下去。

四次挥手

当客户端和服务端通过三次握手建立 TCP 连接进行可靠数据传输后,当数据传送完毕,肯定是要断开TCP连接,这里就有了神秘的“四次挥手”。

  1. 第一次挥手:客户端设置 seq和ack,向服务端发送一个FIN报文段;此时,客户端进入 FIN_WAIT_1 状态;这表示客户端没有数据要发送给服务端了;
  2. 第二次挥手:服务端收到了客户端发送的FIN报文段,向客户端回一个 ACK 报文段,ack 为 seq+1;客户端进入 FIN_WAIT_2 状态;服务端告诉客户端,我“同意”你的关闭请求;
  3. 第三次挥手:服务端向客户端发送 FIN 报文段,请求关闭连接,同时服务端进入 LAST_ACK 状态;
  4. 第四次挥手:客户端收到服务端发送的 FIN 报文段,向服务端发送 ACK 报文段,然后客户端进入 TIME_WAIT状态;服务端收到客户端的 ACK 报文段以后,就关闭连接;此时,客户端等待 2MSL 后依然没有收到回复,则证明服务端已正常关闭,那好,客户端也可以关闭连接了。


思路整理


这里主要使用的是尹圣雨[韩]的著作《TCP/IP网络编程》第 4 章中的简易版回声服务器来进行实验。

所谓回声服务端,就像小时候在回声山谷中玩的游戏一样,你朝山谷中大吼一声“啊”,然后山谷也会给你一个“啊”。回声服务端就是你向服务端发送一个“hello world”,回声服务端也向你回复一个“hello world”。

1、将客户端程序 echo_client.c 放在客户端 A 中,将服务端程序 echo_server.c 放在服务端 B 中

2、在客户端 A 中开启一个命令行窗口,使用 tcpdump 命令监控 A、B 之间的网络通信,并将消息保存为 pacp 文件,方便后续进行抓包分析

3、在服务端 B 中编译程序 echo_server.c,开启服务端程序 echo_server,监听指定端口 2333

这里的端口号可以自己指定,在 1025-65535 之间都可以,主要是因为0-1024已经被系统占用了,比如http的80端口,ssh的22端口。而 Linux 下默认端口数在65535个,所以自己可以指定的端口号就在1025-65535之间。

4、在客户端 A 中编译程序 echo_client.c,并且开启客户端程序 echo_client,指定通话 IP 以及端口号,我在这里就是服务端 B 的IP:192.168.78.130以及 2333 端口号了

5、在客户端 A 中发送消息“hello”,然后按 Q 退出即可

6、通信完毕,将 2 中保存的文件转存到 Windows 环境下,使用大白鲨 Wireshark 进行网络数据包分析。

7、分析抓到的数据包文件


开干


说了那么多,终于可以开始开干了!

1、将echo_client.c 、echo_server.c分别放在客户端A:192.168.78.128 以及服务端B:192.168.78.130 中。

                                                      客户端A

                                                        服务端B

2、  在客户端A中新开一个命令行窗口,输入命令:sudo tcpdump -i any tcp and host 192.168.78.130 and port 2333 -w message.pcap

1、由于tcpdump命令需要管理员权限,所以需要加上sudo命令进而获取管理员权限。

2、这段命令的大概含义就是监控客户端 A:192.168.78.128,和服务端 B:192.168.78.130 之间在端口号2333 上的基于TCP的数据交换,并且保存为 message.pcap 文件

                                               tcpd数据包保存命令

可以看到,我们在输入该条命令后,需要首先输入 Linux 下的密码获取管理员权限,然后就开始监听客户端 A:192.168.78.128,与服务端 B:192.168.78.130之间在端口号2333上的TCP通信了。

3、接下来,我们进入含有 echo_server.c的文件夹,将服务端B的程序进行编译,编译命令为 gcc echo_server.c -o echo_server,可以看到当前文件夹下出现了 echo_server 程序

                                                         编译服务器程序

接下来,开始监听我们预先设置好的端口号 2333,命令为:./echo_server 2333,服务端开始正式监听。

                                          运行服务器程序

4、服务端 B 设置完毕,我们开始转战客户端 A ,在 2 中使用 tcpdump 命令监听的那个端口号不要关闭,千万不要关闭,我们在客户端 A 中另外新开一个命令行。

跟服务端 B 中类似,首先将客户端 A 中的程序echo_client.c进行编译,编译命令:gcc echo_client.c -o echo_client

                                                  编译客户端程序

跟服务端 B 中类似,我们在客户端 A 中开启客户端程序echo_client,指定通话IP :192.168.78.130及端口号 2333

命令为./echo_client 192.168.78.130 2333

                                                              运行客户端程序

可以看到出现 “Connected…..”字样,说明我们已经走完长征两万五千公里,成功会师啦!

客户端 A 与服务端 B 终于成功连接了,这个时候我们再转去看一下服务端 B 的状态。

                                                      服务器程序状态

在服务端 B 的监听窗口也出现了“Connect client 1”字样,换句话说,在服务端看来,有一个客户端与它成功建立连接了。

5、下一步就可以开始通信了,我们在客户端 A 中发送“hello”字样。

                                                        在客户端A发送消息

可以看到,我们在客户端 A 中发送了一条消息“hello”, 服务端 B 也给了我们一个消息“hello”,这也就是我们上文中提到的回声服务端了。

接下来,我们按照提示,输入“Q”结束本次通话。

                                                         退出客户端A

至此,本次通话结束。

6、最后我们在 2 中开启 tcpdump 命令监控的界面中,按下 ctrl+ c ,结束监听。

                                                           保存抓包文件

可以看到,提示我们一共成功捕获了10 个packets,没有数据包丢失。接下来,我们将捕获文件 message.pacp传输到 Windows 下开始进行抓包分析。

 


抓包分析


可以看出一共 10 个数据包,也对应了上文中我们在 Linux 下通过tcpdump命令抓到的数据包个数。其中序号 1-3 为三次握手的数据包,序号 4-7 为两次数据交换的数据包,8-10 为三次挥手的数据包。

                                         抓到的10个数据包

问题1:4-7 为什么是两次数据交换呢?

回答1:我们的回声服务端就是你发送什么数据过去,服务端发送什么数据回来,所以第一次数据交换:客户端A发送数据”hello“到服务端B,B回复 确认收到。这也对应着4、5数据包;第二次数据交换:服务端B发送数据”hello“到客户端A,A回复 确认收到。这也对应着6、7数据包。

问题2:说好的四次挥手呢?这里怎么只有三次了?

回答2: 因为服务端收到客户端的 FIN 后,服务端也可以同时关闭连接,这样就可以把 ACK 和 FIN 两个包合并到一起发送,这样可以节省一个网络包,“四次挥手”变成了“三次挥手”。这样可以节省网络资源,省时又省力。而通常情况下,服务端收到客户端的 FIN 后,很可能还没发送完数据,所以就会先回复客户端一个ACK 包,完成所有数据包的发送后,才会发送 FIN 包,也就是“四次挥手“了。

三次握手过程

三次挥手过程

第一次握手,序号为1,客户端A:192.168.78.128 向服务端B:192.168.78.130 发送SYN请求包,seq为1796975076。

第二次握手,序号为2,服务端 B:192.168.78.130 向客户端A:192.168.78.128 发送 SYN、ACK 请求回复包,seq为1222412335,ack为1796975077,也就是第一次握手中的 seq+1。

第三次握手,序号为3,客户端A:192.168.78.128 向服务端B:192.168.78.130 发送 ACK 确认包,seq为1796975077,ack为为1222412336,也就是第二次握手中的 seq+1。

两次数据交互过程

第一次数据交互:

序号为4,客户端A:192.168.78.128 向服务端B:192.168.78.130 发送 push 消息包,可以看到下方的数据解析为“hello”,并且数据长度 len = 6。

可能有些小伙伴问“hello不是一共5个字符吗?长度应该为5啊。”len = 6是因为“hello“长度为5,再加上结尾的‘\0’,加起来一共就是6了

序号为5,服务端B:192.168.78.130 向客户端A:192.168.78.128 发送 ACK 确认包,表示已经收到该消息。

第二次数据交互:

序号为6,服务端B:192.168.78.130 客户端A:192.168.78.128发送push消息包,可以看到下方的数据解析为“hello”,并且 len = 6。

序号为7,客户端A:192.168.78.128 向服务端B:192.168.78.130  发送ACK确认包,表示已经收到该消息。

三次挥手过程

正式的四次挥手如下图所示:

标准的四次挥手

我们所抓到的三次挥手如下所示:

第一次挥手,序号为8:客户端A:192.168.78.128 向服务端B:192.168.78.130  发送 FIN 请求断开连接包,表示主动请求断开链接。

第二三次挥手,序号为9:服务端B:192.168.78.130 向  客户端A:192.168.78.128发送 FIN、ACK 确认并请求断开消息包,表示收到上次断开连接的请求,并请求断开服务端到客户端的链接。

可以看出,我们所抓的包中,将第二次挥手和第三次挥手合并为一个数据包了,也就是192.168.78.130->192.168.78.128的包中既有FIN也有ACK,所以这也是三次挥手而不是四次挥手的原因。

第四次挥手,序号为 10:客户端A:192.168.78.128 向服务端B:192.168.78.130  发送 ACK 确认包,表示收到服务端发送过来的请求断开连接消息,并给予回复。


结语


学会将自己所学的知识串联起来是你迈向大佬的必经之路

授人以鱼不如授人以渔,本次实战的全部文件已经打包分享出来了,公众号后台回复【回声服务器】就可以获取,你也可以自己动手实践一下。毕竟“纸上得来终觉浅,绝知此事要躬行“。

如果大家觉得这种实战类型的文章还可以的话,还请留言告诉我,以后我多为大家带来这种实战类型的文章。

对了欢迎抽奖,后台直接回复【抽奖】即可,公众号抽奖的人数不多,中奖概率还是挺大的,溜了溜了。

巨人的肩膀

https://my.oschina.net/u/658658/blog/417739

《TCP/IP网络编程》- 尹圣雨[韩]

《Wireshark网络分析就这么简单》- 林沛满

《Wireshark网络分析的艺术》- 林沛满

《计算机网络-自顶向下方法》- ames F. Kurose、Keith W. Ross

《TCP/IP详解 卷1:协议》- kevin R.Fall W.Richard Stevens


往期推荐


双非渣硕的秋招之路总结(已拿抖音研发岗SP)

一份百投百中的计算机校招简历是如何迭代足足26版的?

个人C++学习路线大公开

— END —

Hi,小伙伴你好,我是阿秀,一枚从底层慢慢爬到互联网大厂的程序员,每一篇原创文章都是我精心创作、慢慢打磨出来的,如果你觉得本文对你有所帮助,麻烦点亮一下「」和「在看」,也可以「分享」给需要的小伙伴,阿秀真的很需要你的点亮,十分感谢!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
这篇文章介绍了如何使用PyTorch框架,结合CIFAR-10数据集,通过定义神经网络、损失函数和优化器,进行模型的训练和测试。
96 2
目标检测实战(一):CIFAR10结合神经网络加载、训练、测试完整步骤
|
29天前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
105 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
19天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
60 6
|
2月前
|
安全 算法 网络安全
网络安全与信息安全:构建数字世界的坚固防线在数字化浪潮席卷全球的今天,网络安全与信息安全已成为维系社会秩序、保障个人隐私和企业机密的关键防线。本文旨在深入探讨网络安全漏洞的本质、加密技术的前沿进展以及提升公众安全意识的重要性,通过一系列生动的案例和实用的建议,为读者揭示如何在日益复杂的网络环境中保护自己的数字资产。
本文聚焦于网络安全与信息安全领域的核心议题,包括网络安全漏洞的识别与防御、加密技术的应用与发展,以及公众安全意识的培养策略。通过分析近年来典型的网络安全事件,文章揭示了漏洞产生的深层原因,阐述了加密技术如何作为守护数据安全的利器,并强调了提高全社会网络安全素养的紧迫性。旨在为读者提供一套全面而实用的网络安全知识体系,助力构建更加安全的数字生活环境。
|
1月前
|
机器学习/深度学习 数据可视化 测试技术
YOLO11实战:新颖的多尺度卷积注意力(MSCA)加在网络不同位置的涨点情况 | 创新点如何在自己数据集上高效涨点,解决不涨点掉点等问题
本文探讨了创新点在自定义数据集上表现不稳定的问题,分析了不同数据集和网络位置对创新效果的影响。通过在YOLO11的不同位置引入MSCAAttention模块,展示了三种不同的改进方案及其效果。实验结果显示,改进方案在mAP50指标上分别提升了至0.788、0.792和0.775。建议多尝试不同配置,找到最适合特定数据集的解决方案。
306 0
|
6天前
|
API
鸿蒙开发:切换至基于rcp的网络请求
本文的内容主要是把之前基于http封装的库,修改为当前的Remote Communication Kit(远场通信服务),无非就是通信的方式变了,其他都大差不差。
鸿蒙开发:切换至基于rcp的网络请求
|
20天前
|
数据采集 前端开发 中间件
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第26天】Python是一种强大的编程语言,在数据抓取和网络爬虫领域应用广泛。Scrapy作为高效灵活的爬虫框架,为开发者提供了强大的工具集。本文通过实战案例,详细解析Scrapy框架的应用与技巧,并附上示例代码。文章介绍了Scrapy的基本概念、创建项目、编写简单爬虫、高级特性和技巧等内容。
46 4
|
20天前
|
网络协议 物联网 API
Python网络编程:Twisted框架的异步IO处理与实战
【10月更文挑战第26天】Python 是一门功能强大且易于学习的编程语言,Twisted 框架以其事件驱动和异步IO处理能力,在网络编程领域独树一帜。本文深入探讨 Twisted 的异步IO机制,并通过实战示例展示其强大功能。示例包括创建简单HTTP服务器,展示如何高效处理大量并发连接。
39 1
|
1月前
|
XML 开发工具 Android开发
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
ExoPlayer最初是为了解决Android早期MediaPlayer控件对网络视频兼容性差的问题而推出的。现在,Android官方已将其升级并纳入Jetpack的Media3库,使其成为音视频操作的统一引擎。新版ExoPlayer支持多种协议,解决了设备和系统碎片化问题,可在整个Android生态中一致运行。通过修改`build.gradle`文件、布局文件及Activity代码,并添加必要的权限,即可集成并使用ExoPlayer进行网络视频播放。具体步骤包括引入依赖库、配置播放界面、编写播放逻辑以及添加互联网访问权限。
136 1
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
|
21天前
|
网络协议 安全 NoSQL
网络空间安全之一个WH的超前沿全栈技术深入学习之路(8-2):scapy 定制 ARP 协议 、使用 nmap 进行僵尸扫描-实战演练、就怕你学成黑客啦!
scapy 定制 ARP 协议 、使用 nmap 进行僵尸扫描-实战演练等具体操作详解步骤;精典图示举例说明、注意点及常见报错问题所对应的解决方法IKUN和I原们你这要是学不会我直接退出江湖;好吧!!!
网络空间安全之一个WH的超前沿全栈技术深入学习之路(8-2):scapy 定制 ARP 协议 、使用 nmap 进行僵尸扫描-实战演练、就怕你学成黑客啦!