温馨提示:这篇文章已超过386天没有更新,请注意相关的内容是否还可用!
摘要:,,本文介绍了基于TCP协议的Socket通讯的网络基础。TCP协议是一种可靠的、面向连接的传输层协议,用于保证数据传输的可靠性和顺序性。Socket通讯则是网络编程中常用的通信方式,通过Socket可以实现不同主机间的进程通信。本文阐述了Socket通讯的基本原理和TCP协议的作用,为网络编程提供了基础知识和重要参考。
UDP的Socket编程相对简单,这里不再赘述。
(插入TCP Socket通讯流程图图片)
服务端程序启动
服务端程序首先需要启动并等待客户端的连接和数据,服务端程序首先调用socket()函数,创建网络协议为IPv4、传输协议为TCP的Socket,调用bind()函数为这个Socket绑定一个IP地址和端口。
绑定IP地址和端口的目的如下:
1、绑定端口的目的:当内核收到TCP报文时,通过TCP头中的端口号来找到我们的应用程序,然后将数据传递给我们。
2、绑定IP地址的目的:一台机器通常拥有多个网卡,每个网卡都有对应的IP地址,当绑定一个特定网卡的IP地址时,只有该网卡上收到的数据包才会被发送给该Socket。
绑定完IP地址和端口后,服务端可以调用listen()函数进行监听,要判断服务器中网络程序是否已启动,可以通过netstate命令查看对应端口是否处于监听状态,服务端进入监听状态后,通过调用accept()函数从内核获取客户端的连接,如果没有客户端连接,accept()函数会阻塞等待客户端连接的到来。
客户端发起连接
客户端在创建好Socket后,调用connect()函数发起连接,该函数的参数需指明服务端的IP地址和端口号,随后,万众期待的TCP三次握手过程开始。
在TCP连接过程中,服务器的内核为每个Socket维护了两个队列:
1、还未完全建立连接的队列,称为TCP半连接队列,这个队列中的连接尚未完成三次握手,服务端处于syn_rcvd状态。
2、已建立连接的队列,称为TCP全连接队列,这个队列中的连接已完成了三次握手,服务端处于established状态。
当TCP全连接队列不为空时,服务端的accept()函数会从内核的TCP全连接队列中取出一个已完成连接的Socket返回给应用程序,后续的数据传输都使用这个Socket。
注意,监听的Socket和用于数据传输的Socket是两个不同的Socket:监听Socket用于接受连接请求,而已连接Socket用于数据传输。
连接建立后,客户端和服务端开始相互传输数据,双方都可以通过send()和recv()函数来读写数据。
四、socket中的send()和recv()函数
(插入send()和recv()函数相关流程图图片)
在发送数据端,通过TCP连接发送的数据首先会拷贝到send buffer中,这个过程可以通过send()函数完成,由于也可以使用write()函数写入数据,所以这个过程也称为写数据,send buffer中的数据会通过DMA(直接内存访问)的方式拷贝到网卡中并通过网络传输给TCP连接的另一端(接收端)。
在接收数据端,通过TCP连接接收的数据先通过网卡流入,然后通过DMA方式拷贝到recv buffer中,通过recv()函数将数据从recv buffer拷入到用户空间的应用程序缓冲区中。
客户端主动关闭
(插入客户端主动关闭流程图片)
当客户端主动调用close()函数时,会向服务端发送FIN报文,进入FIN_WAIT_1状态,服务端接收到FIN报文后,TCP协议栈会在接收缓冲区中插入一个文件结束符EOF,服务端处理完数据并读取到EOF后,也会调用close()函数关闭其Socket,并发送FIN包进入LAST_ACK状态,客户端接收到服务端的FIN包并发送ACK确认包后,进入TIME_WAIT状态,服务端收到ACK确认包后,进入最后的CLOSE状态,客户端在经过一定时间(2MSL)后,也进入CLOSED状态,这就是TCP连接的四次挥手过程。
参考:
[博客链接](此处应插入相关博客链接)
硬不硬你说了算!近40张图解被问千百遍的TCP三次握手和四次挥手面试题。
还没有评论,来说两句吧...