了解Socket大致可以分为什么是Socket、Socket如何创建、Socket如何连接发送和接收数据以及如何删除Socket。
Socket 是什么以及创建过程
数据包由应用程序产生,进入协议栈封装各种消息头。然后操作系统调用网卡驱动程序指示硬件将数据发送到另一侧的主机。下面是整个过程的示意图:
如您所知,协议栈实际上是操作系统中的协议栈,例如TCP、UDP、ARP、ICMP 和IP。特定的协议通常是为了解决特定的问题而设计的。例如,TCP旨在安全可靠地发送数据,UDP旨在具有小数据包并高效传输,ARP旨在查询物理设备(Mac)。 ICMP 旨在通过IP 地址向主机返回错误消息,而IP 旨在大规模互连主机。
浏览器、电子邮件和文件传输服务器等应用程序生成的数据通过传输层协议进行传输。应用程序并不直接与传输层建立连接,但它们确实具有可以连接应用层和传输层的链路。它们之间的套件是Socket。
在上图中,应用程序包括一个套接字和一个解析器。解析器的作用是向DNS服务器发起查询以获取目标IP地址。
应用程序的底层是操作系统的内部,而协议栈是协议栈。操作系统下面是网卡驱动程序,它控制网卡硬件完成发送和接收任务。
在操作系统内部,有一个用于存储控制信息的存储区域,该存储区域记录了用于控制通信的控制信息。实际上,这个控制信息就是socket实体,或者说存储控制信息的内存空间就是socket实体。
由于您可能不知道这里的原因,因此我使用netstat 命令向您展示套接字是什么。
在Windows 命令提示符处,键入
netstat -ano# netstat 用于显示套接字的内容。 -ano 是可选的。 # a 不仅显示正在通信的套接字,还显示所有套接字,包括尚未开始通信的套接字。 # n 显示IP地址和端口号。 # o 显示套接字的程序PID。在我的计算机上我得到以下结果:
图中的每一行对应一个套接字,每一列也称为一个元组,因此一个套接字是一个5元组:协议、本地地址、外部地址、状态和PID。尽管有时称为4x,但4x 不包括协议。
例如,在图中的第一行中,协议是TCP,本地和远程地址都是0.0.0.0。这意味着通信还没有开始,IP地址还没有确定,已知本地端口是135,但还不知道远程端口。此时的状态是“LISTENING”,这意味着应用程序已打开并等待与远程主机建立连接(用于在各个主机之间进行转换)。最后一个元组是PID,它就像身份证号码一样,允许我们查明唯一的进程。
我希望您现在了解套接字的基础知识。喝一口水,休息一下,然后继续探索Sockets。
现在的问题是,Socket是如何创建的呢?
套接字是与应用程序一起创建的。应用程序有一个socket组件,调用socket应用程序,根据应用程序创建socket。在这一步中,我们首先为套接字分配所需的内存空间。和准备一个容器来存储控制信息是一样的,但是容器本身并没有真正的作用,所以如果不请求socket创建所需的内存空间,也必须将控制信息存储在容器中。您创建的文件也将变得无法使用。由于有地方可以保存,因此确保存储区域和放置控制信息至关重要。至此,socket创建完成。
创建套接字时,会将套接字描述符返回给应用程序。该描述符对应于区分不同插座的号码牌。根据这个描述符,应用程序在委托协议栈发送或接收数据时必须提供这个描述符。
套接字连接
创建套接字后,您最终将发送和接收数据。在发送或接收数据之前,需要一个连接步骤,即建立连接的过程。这种连接不是真正的连接。两台计算机之间插入一根水管。
相反,它是应用程序通过TCP/IP 协议标准通过网络介质从一台主机传输到另一台主机的过程。
当套接字刚刚创建时,它还没有数据,也不知道通信对象。在这种状态下,即使客户端应用程序将发送数据委托给协议栈,它也不知道将其发送到哪里。因此,浏览器必须根据URL查询服务器的IP地址。执行此操作的协议是DNS。此时,浏览器告诉协议栈目标主机的IP地址。客户已经准备好了。
您需要在服务器和客户端上创建套接字,但由于您不知道正在与谁通信,因此需要告诉服务器客户端需要的信息(IP 地址和端口号)。
通信的两个方已经拥有建立连接所需的信息。你所需要的只是东南风。通信端接收到数据后,还需要一个地方来存储它。该位置可以使用缓冲区来发送和接收数据。
现在,客户端想要向服务器发送数据,但是应该做什么呢?
首先,客户端应用程序必须调用套接字库的connect 方法,指定套接字描述符以及服务器的IP 地址和端口号。
连接(描述符、服务器IP地址和端口号)信息被传递到协议栈中的TCP模块,该模块封装请求消息并将其传递到IP模块以封装IP头。在物理层,帧头被封装并通过网络介质传递到服务器,服务器解析帧头、IP模块和TCP模块头以找到相应的套接字。然后就会写入相应的信息并连接状态。一旦请求过程完成,服务器的TCP 模块就会返回响应。这个过程和客户端过程是一样的(如果不熟悉消息头封装过程,请参考作者的文章《TCP概述》)。 /IP基础知识)
控制信息在整个请求-响应过程中起着非常重要的作用(我们稍后会讨论它的具体作用)。
SYN是同步的缩写,客户端首先通过发送SYN数据包请求服务器建立连接。 ACK表示响应,是对发送SYN包的响应。 FIN 表示终止,表示客户端/服务器想要结束连接。在复杂多变的网络环境中,经常会出现丢包的情况,因此在通信过程中,双方都需要确认对方的数据包是否到达,而ACK值就是这个判断的标准。
(两个通信方之间建立连接涉及到三次握手过程,有关三次握手的更多信息,请参见作者的文章《TCP基础知识》。)
如果建立连接的所有消息都发送和接收成功,则该套接字处于收发状态,可以认为两个套接字是在一个管理下连接的。当然,这个管实际上并不存在。一旦连接建立,协议栈连接操作就完成了。这意味着连接已建立并且控制流已返回到应用程序。
收发数据
当控制流从连接返回到应用程序时,直接进入数据发送和接收阶段。数据发送/接收操作从应用程序调用write 开始,将要发送的数据传递到协议栈。协议栈接收数据并执行发送操作。
由于数据最终会转换为二进制序列,因此协议栈收到数据后并不会立即发送数据,而是将数据放入发送缓冲区中。选择并等待应用程序发送下一个数据。
为什么接收到的数据包放在缓冲区而不是直接发送?
由于数据一收到就发送,因此有可能发送大量小数据包,从而降低网络效率。因此,协议栈在发送数据之前必须将数据积累到一定数量。关于协议栈应缓冲多少数据的观点因操作系统版本和类型而异。但是,所有操作系统和类型都遵循以下标准:
第一个决定因素是网络数据包可以容纳的数据长度。标准是MTU,它代表网络数据包的最大长度。最大长度包括报头,因此当仅讨论数据区域时,我们使用报头长度MTU,并将所得的最大数据长度称为MSS。
另一个标准是时间。如果应用程序生成的数据相对较少,并且协议栈缓冲数据的效率不高,则每次发送时都要等到MSS才发送,可能会因为等待时间过长而导致延迟。这种情况下,即使数据长度没有到达MSS,也需要发送数据。协议栈不知道如何平衡这两个元素。优先考虑数据长度会降低效率,优先考虑时间会降低网络效率。
有一阵子了。
现在假设缓冲区已满,协议栈尝试发送数据,却发现无法发送这么大量的数据。 (相对)一下子全部完成,那么你该怎么做呢?
在这种情况下,传输缓冲区中的数据被分为MSS 大小的单个数据包,并且每个片段都附加有TCP、IP 和以太网标头。然后将其放入另一个网络数据包中。
现在您已准备好向服务器发送网络数据包,但服务器尚未检查是否收到网络数据包,因此数据发送操作尚未完成。因此,即使客户端发送了数据包,服务器也必须对其进行确认。
TCP模块在分割数据时,会计算一个网络包偏移量,即从数据开头算起的字节数,并写入TCP模块的网络包序号。 (SYN) 也被生成。该序列号是唯一的,用于服务器验证。
服务器验证客户端发送的数据包正确后,生成序列号和确认号(ACK),客户端验证后发送确认。将号码发送到服务器。
让我们看看它在实践中是如何运作的。
首先,客户端在连接时必须计算出序列号的初始值,并将该值发送给服务器。然后服务器根据该初始值计算确认编号并将其返回给客户端。由于通信过程中初始值可能会被丢弃,因此服务器在接收到初始值时必须返回一个确认号进行确认。同时,服务器还必须计算服务器到客户端序列号的初始值,并将该值发送给客户端。然后客户端还需要根据服务器发送的初始值计算出一个确认数并发送给服务器。此时连接已建立,可以进入数据发送和接收阶段。
在数据发送和接收阶段,通信双方可以同时发送请求和响应,双方也可以同时确认请求。
请求确认机制非常强大,允许接收方检查是否已收到特定数据包,如果没有收到则重新传输,并立即检测网络中发生的任何错误。和补救措施。
网卡、集线器和路由器没有错误恢复机制。如果检测到错误,则直接丢弃该数据包。此机制仅适用于TCP/IP 模块。
由于复杂多变的网络环境会导致数据包丢失,因此TCP通过窗口来管理确认号。本文不会详细解释。在这位作者的文章中寻找答案。
断开连接
当通信双方不再需要发送或接收数据时,必须断开连接。不同的应用程序需要不同的断开时间。以Web为例,浏览器向Web服务器发送请求消息,Web服务器返回响应消息。此时,服务器已经完成了所有数据的发送和接收,可以发起断开连接响应。当然,客户端可以先发起(无论谁先发起),但断开连接是应用程序做出的决定,与协议栈无关。
无论哪一方发起断开请求,都会调用socket库的close程序。我们以服务器断线为例。服务器发起断开连接请求,协议栈实际上设置FIN位并向IP模块发送数据。同时,服务器的套接字会记录有关断开连接的信息。
客户端协议栈收到服务器端的FIN请求后,将套接字标记为已断开,并向服务器端返回一个确认号。这是切割的第一步。然后应用程序也会断开连接。调用read来读取数据。当服务器数据发送时,协议栈通知客户端应用程序数据已被接收。
只要接收到服务器返回的所有数据,客户端就调用close程序结束发送/接收操作。此时,客户端产生FIN,并在一段时间后发送给服务器。服务器返回一个ACK号。至此,客户端与服务器端的通信结束。
删除套接字
一旦通信完成,用于通信的套接字将不再使用。此时您可以删除套接字。但是,此时套接字并不会立即删除,而是在一段时间后删除。
这次等待的目的是为了防止误操作。最常见的错误是客户返回的确认号码丢失。等待多长时间与数据包如何重传有关。
原创文章,作者:小条,如若转载,请注明出处:https://www.sudun.com/ask/85330.html