前言

大家好,我是阿秀

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

今天带大家实战一把,真实体验服务端底层数据交换的点点滴滴,在这过程中可以让你看见 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 最经典的三次握手与四次挥手

三次握手四次挥手

三次握手

第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为1,seq(Sequence Number) 为 x;然后,客户端进入 SYN_SEND 状态,等待服务端的确认;

第二次握手:服务端收到 SYN 报文段。服务端收到客户端的 SYN 报文段,需要对这个SYN 报文段进行确认,设置 ack(Acknowledgment Number) 为 x+1 (也就是 seq+1);同时,自己还要发送 SYN 请求信息,将 SYN 位置为1,seq 为 y;服务端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务端进入 SYN_RECV 的状态;

第三次握手:客户端收到服务端的 SYN+ACK 报文段。然后将ack设置为y+1,向服务端发送ACK报文段,这个报文段发送完毕以后,客户端和服务端端都进入 ESTABLISHED 状态,完成TCP三次握手。

数据交互

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

四次挥手

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

第一次挥手:客户端设置 seq和ack,向服务端发送一个FIN报文段;此时,客户端进入 FIN_WAIT_1 状态;这表示客户端没有数据要发送给服务端了;

第二次挥手:服务端收到了客户端发送的FIN报文段,向客户端回一个 ACK 报文段,ack 为 seq+1;客户端进入 FIN_WAIT_2 状态;服务端告诉客户端,我“同意”你的关闭请求;

第三次挥手:服务端向客户端发送 FIN 报文段,请求关闭连接,同时服务端进入 LAST_ACK 状态;

第四次挥手:客户端收到服务端发送的 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 确认包,表示收到服务端发送过来的请求断开连接消息,并给予回复。

结语

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

巨人的肩膀

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

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

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

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

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

—END—

“你只管努力,剩下的交给时间就好,我就是活生生的例子~”

计算机网络拓跋结构,实战 | 服务端开发与计算机网络结合的完美案例相关推荐

  1. 第13章 Kotlin 集成 SpringBoot 服务端开发(1)

    第13章 Kotlin 集成 SpringBoot 服务端开发 本章介绍Kotlin服务端开发的相关内容.首先,我们简单介绍一下Spring Boot服务端开发框架,快速给出一个 Restful He ...

  2. 抖音、腾讯、阿里、美团春招服务端开发岗位硬核面试(二)

    在上一篇 文章中,我们分享了几大互联网公司面试的题目,本文就来详细分析面试题答案以及复习参考和整理的面试资料,小民同学的私藏珍品????. 首先是面试题答案公布,在讲解时我们主要分成如下几块:语言的基 ...

  3. 一场B站服务端开发面试之旅

    作者 | 蓝 来源 | 我是程序员小贱(ID:Lanj1995Q) 此次B站服务端开发面试之旅可谓惊险,不过通过对大部分面试题套路的掌握,不出意外还是拿下了,下面我们来看看这些题是不是常见的不能再常见 ...

  4. NodeJS+Express+mySQL服务端开发详解

    NodeJS+Express+mySQL服务端开发详解 随着NodeJS的发展,现在已经被很多人熟知,NodeJS已经成为了前端开发人员必备的技能.本文不会对NodeJS过多介绍 如果你感兴趣可以访问 ...

  5. 一、服务端开发基础(搭建Web服务器、网络基础概念、请求响应流程、配置Apache、静态网站与动态网站)

    一.建立你的第一个网站(目标) 前端开发 最终还是属于 Web 开发 中的一个分支,想要成为一名合格的前端开发人员,就必须要 充分理解Web 的概念. 构建一个专业的网站是一项巨大的工作!对于新手我们 ...

  6. 奇虎360WEB平台部招贤纳士之服务端开发

    部门介绍 招聘部门:WEB平台部 WEB平台部是奇虎360的技术支持部门,为公司各业务线提供互联网行业全方位的技术支持和解决方案.WEB平台部包含业内知名的前端团队奇舞团,测试团队Qtest,基础研发 ...

  7. 百万在线:大型游戏服务端开发

    进入手游时代,服务端技术也在向前演进.现代游戏服务端既要承载数以万计的在线玩家,又要适应快速变化的市场需求,因此,如何设计合适的架构就成了重中之重.服务端技术并不简单,作为服务端新人,全面掌握服务端技 ...

  8. 伪装成mysql的备_如何伪装成一个服务端开发(六) -- 数据库操作

    目录 如何伪装成一个服务端开发(六) 前言 本篇开始学习Spring 的数据库连接. 术语 数据库连接涉及到一些术语,如果在学习之前没有搞清楚,很容易在业务理解上出现偏差. JDBC : Java D ...

  9. 2016届360公司PHP服务端开发笔试和面试之所得所感

    这是一篇叙述自己在360公司参加笔试和面试的过程,可能面试的职位并不是你所学的方向,但是如果你能从中学到些什么或者吸取我的教训,那么作者就非常知足了.本着"学习别人是怎么失败的,活着出来的人 ...

最新文章

  1. python 中遍历表时候,当指定的表的长度超过实际长度时候,实际遍历的长度以表实际长度为准,不会发生越界,如下
  2. Linux之 proc文件系统
  3. Asp.net PageBase学习总结
  4. android 恶意广告,CheckPoint:Android恶意广告软件SimBad被下载近1.5亿次
  5. java 子类 复制_关于java子类继承来的属性与方法究竟是完全复制还是共用使用...
  6. 文本”Hello, world.”显示的颜色是?
  7. Hadoop HDFS概念学习系列之HDFS升级和回滚机制(十二)
  8. Spring简化Java开发_spring如何简化java开发
  9. var s=+newDate();的用法,表示对应的时间截
  10. 深入理解CSS权重(优先级)
  11. 可变字典 NSMutableDictionary
  12. MPEG-7实例入门
  13. Linux添加磁盘和挂载
  14. 单片机c语言取反符号怎么打,arduino取反怎么写
  15. 浅谈12306核心模型设计思路和架构设计
  16. MySQL的函数-窗口函数
  17. ucla计算机科学博士排名,加州大学洛杉矶分校专业排名一览及最强专业推荐(QS世界大学排名)...
  18. 夏季室内甲醛净化 A.O.史密斯数显甲醛净化器让用户更放心
  19. 【MAUI】条形码,二维码扫描功能
  20. win10安装打印机驱动程序失败“试图将读懂程序添加到存储区时遇到问题”

热门文章

  1. 你应该知道的jQuery技巧【收藏】
  2. python- 基础 range方法的使用
  3. oracle 创建view时,授权给用户
  4. /dev/null 文件
  5. 使用virt-install安装kvm虚拟机时需要的问题
  6. 结对开发Ⅴ——循环一维数组求和最大的子数组
  7. 教育行业的互联网焦虑症
  8. 一个古怪的VISTA网络问题解决的坎坷经历
  9. 本地无法启动MySQL服务,报的错误:1067,进程意外终止---解决
  10. Bookshelf 2 简单DFS