高士涛-学习日报

姓名

高士涛

日期

2023/05/10

部门

云服务业务部

导师

王晓明

学习工作内容

1. TCP连接原理

2. 基于C语言的TCP连接的实现

一、TCP连接原理

HTTP通信由TCP/IP承载的,TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交换网络分层协议集。客户端应用程序可以打开一条TCP/IP连接,连接到可能运行在世界任何地方的服务器应用程序。一旦连接建立,在客户端和服务器的计算机之间交换的报文就永远不会丢失、受损或失序。

1TCP连接的建立(三次握手)

TCP协议目的是为了保证数据能在两端准确连续的流动,可以想象两个建立起TCP通道的设备就如同接起了一根水管,数据就是水管中的水由一头流向另一头。然而TCP为了能让一个设备连接多根水管,让一个设备能同时与多个设备交互信息,它必须要保证不同水管之间不会产生串联或相互影响。

为了确保数据能够正确分发,TCP用一种叫做TCB,也叫传输控制块的数据结构把发给不同设备的数据封装起来,我们可以把该结构看作是信封。一个TCB数据块包含了数据发送双方对应的socket信息以及拥有装载数据的缓冲区。

在两个设备要建立连接发送数据之前,双方都必须要做一些准备工作,分配内存建立起TCB数据块就是连接建立前必须要做的准备工作。

 

1)准备工作

最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。

TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态。

2)一次握手:

TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号seq=x

此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。

3)二次握手:

TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该ACK=1SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。

ACK1表示确认号有效,为0表示报文中不包含确认信息。

4)三次握手:

TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。

当服务器收到客户端的确认后也进入established状态,此后双方就可以开始通信了。

注:tcp建立连接需要三次握手,SYN是发送标志位,ACK是确认标志位

 

【为什么TCP客户端最后还要发送一次确认呢?】

主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

 

【为什么要3次握手?】

换个易于理解的视角来看为什么要3次握手。

客户端和服务端通信前要进行连接,3次握手的作用就是双方都能明确自己和对方的收、发能力是正常的。

第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。从客户端的视角来看,我接到了服务端发送过来的响应数据包,说明服务端接收到了我在第一次握手时发送的网络包,并且成功发送了响应数据包,这就说明,服务端的接收、发送能力正常。而另一方面,我收到了服务端的响应数据包,说明我第一次发送的网络包成功到达服务端,这样,我自己的发送和接收能力也是正常的。

第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。 第一、二次握手后,服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时,服务端收到了客户端对第二次握手作的回应。从服务端的角度,我在第二次握手时的响应数据发送出去了,客户端接收到了。所以,我的发送能力是正常的。而客户端的接收能力也是正常的。

经历了上面的三次握手过程,客户端和服务端都确认了自己的接收、发送能力是正常的。之后就可以正常通信了。

 

2. TCP连接的释放(四次挥手)

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于established(表示连接已经建立)状态,然后客户端主动关闭,服务器被动关闭。

1TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送;

2)服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号;

3)服务器关闭客户端的连接,发送一个FIN给客户端;

4)客户端发回ACK报文确认,并将确认序号设置为收到序号加1

 

【原文链接:TCP连接原理_悠然予夏的博客-CSDN博客

【参考链接:TCP连接建立过程_tcp连接的建立过程_无敌狗剩的博客-CSDN博客

 

 

二、基于C语言的TCP连接的实现

1. 服务器端C程序

server.c

 

2. 客户端C程序

client.c

 

3. 创建测试文件

testFile.txt

测试文件随便写入一些内容:

 

4. 编译server.c为可执行程序server

 

5. 编译client.c为可执行程序client

 

6. 在不启动服务端server的情况下,直接启动客户端client,提示无法连接到服务端

 

7. 先启动服务端server,然后再启动客户端client,可以连接成功

 

8. 传输文件测试

1)在客户端下载服务端的文件,提示可以成功下载:

2)查看实际文件下载结果,已经成功下载测试文件:

 

9. 直接Ctrl+Z退出服务端运行界面,尝试再次启动服务端sever,发现端口被占用,说明刚才只是退出了服务端的界面,但是服务端进程还在运行着

 

10. 想办法彻底关掉服务端sever进程

1)首先,我们通过命令“ps aux | grep server”找到对应进程的进程ID,也就是PID

 

2)通过“kill -l”命令查看杀进程的操作信号,可以看出是9

 

3)通过“kill -9 PID”来彻底关掉server的进程,然后再重新尝试启动server程序,这次终于成功了:

 

 

遗留问题

 Linux程序与进程

明日计划

继续深入学习