Linux网络协议栈与网络体系结构

网络体系结构与网络协议栈

1.物理层-网络设备驱动程序

网络设备驱动程序是网络物理设备与Linux内核之间的一个桥梁,是将网络设备从主机外界:计算机网上收到的数据,从网络设备的数据空间传到内核空间的软件,也就是网络设备驱动程序是网络设备硬件与Linux内核的接口。

网络设备驱动程序的构成:

1.模块初始化/清除功能

任何网络设备实例在进行正常工作状态前都必须初始化,所以网络设备驱动程序首先需要一个模块的初始化函数,当网络设备驱动程序以模块方式装载到内核中,该函数在装载网络设备驱动程序模块时被执行。它创建网络设备实体对应的数据结构实例,初始化部分网络设备实际的数据域,然后调用驱动程序函数完成对网络设备实例的特殊数据域的初始化。

2.网络硬件设备探测函数

网络设备驱动程序直接编译到内核时,如果在内核配置时选择了某个网卡作为系统网络通信的设备,内核在启动过程中会首先探测指定的网络设备硬件,一旦探测到安装的网络设备硬件后,就调用网络设备驱动程序的初始化函数来初始化一个网络设备驱动程序实例。

3.设备活动

网络设备经过创建、初始化后注册到内核,由用户激活,就可以开始网络数据包的收发操作,是异步进行的。

4.管理任务

在网络数据包的收发中可能会出错,设备驱动程序需要对出现的错误做处理,同时内核以及用户程序有时需要获取数据收发的各项统计数据。

网络设备与内核的交互

几乎所有的网络设备与内核通信都使用轮询或者中断模式,或者两者结合。

交互方式:

1.轮询:内核每隔一段时间就查询设备状态,看设备是否有数据需要与内核交换,这是通过读设备的状态来判断的,比较耗费cpu时间,数据交换慢。

2.中断:在系统运行中,如果发生某种随机事件,cpu将暂停现行线程的执行,转去执行为该随机事件服务的中断处理程序,中断处理程序执行完成后自动恢复原程序的执行。它满足了网络数据包的发送与接收可以异步进行的要求,使cpu和网络设备之间可以并行工作。但是在网络负载很高时,网络设备每收到一个数据包就会产生一个中断请求,cpu就要从现行程序切换到中断处理程序,然后再切换回去,就会耗费很多时间。还有一个问题就是网络数据包的收发分为两个阶段:首先网络设备驱动程序将数据包从硬件缓冲区复制到内核接收队列,然后是由内核tcp/ip协议栈来处理数据包。在第二个阶段,将数据包从接收队列移走并处理的程序一直没有机会执行,因为它的优先级较低,这样可能导致系统崩溃:cpu接收队列满后,内核以及没有空间可以容纳新的数据包,而旧的数据包又无法处理,因此cpu没有时间运行数据包处理程序。

中断方式在数据流量较低时适合网络数据的收发,和数据包处理的并行工作,但是网络流量很大时容易出现问题。Linux网络体系结构对此做了扩展。

3.在中断期间处理多个数据包:当中断产生并开始执行网络设备驱动程序的中断服务程序后,中断处理程序就不断从网络上接收数据包放入内核的接收队列,直到接收的数据包数量已经达到事先预定的一次可以接收的最大域值。这里要注意在中断处理程序中需要禁止所有其他的硬件中断,所以某个中断处理程序不能执行太长时间。Linux内核网络子系统中实现的新式接口NAPI对此做了优化:内核不必禁止所有硬件中断,只需要禁止当前有数据包进入,cpu正在执行中断处理程序的网络设备的硬件中断。

网络设备驱动程序的实现

1.网络适配器初始化:linux系统在具备网络功能之前,需要识别系统中的网络设备,将网络设备对应的数据结构实例加入到系统的全局网络设备管理链表中,因此驱动程序要提供一个probe函数来负责探测驱动程序自己的设备,并初始化它的数据结构实例。内核启动时调用netcard_probe自动探测函数,为网络设备的数据结构实例分配空间,然后查看内核启动时有无命令行参数给出设备的配置信息,如果有的话就将其保存在数据结构的相关数据域中,调用探测函数查看是否有该硬件。随和调用探测函数的包装函数do_net_probe,探测网卡的情况,然后将参数传递给实际探测函数netcard_probe1,在网络设备的自动探测过程中,一旦我们选择了要探测网络设备的IO端口基地址,实际探测函数就测试指定设备是否出现在该地址上。为了实现这个测试,函数必须查看指定的网卡,因此对网络设备的访问应该限制在特定的IO端口,以保证读的不是别的适配器信息。

网络设备活动的功能函数:open和stop方法,数据传输、数据发送超时处理等等。

2.数据链路层-数据帧的收发

数据包在数据链路层的接收处理:linux内核在数据链路层实现了一种新的处理输入数据帧的API,也就是NAPI,

数据包在数据链路层的发送处理:向外发送数据帧时,首先处理两个问题:1.如果数据帧由本地主机产生,存放在Socket Buffer中的网络数据帧已经由tcp/ip协议栈的上层协议实例处理完成,应该如何提供数据链路层的方法来启动网络设备硬件将数据帧发送到网络介质上。2.如果向外发送的数据不是本机产生,是本机从网络上接收到的数据帧,需要通过本机继续向前发送,这样的数据帧发送路径应该如何确定。

关键数据结构

在tcp/ip协议栈中,数据链路层的关键任务是:将由网络设备驱动程序从硬件缓冲区复制到内核地址空间的网络数据帧挂到cpu的输入序列,并通知上层协议有网络数据帧到达,然后上层协议就可以从cpu的输入队列中获取网络数据帧并处理。上层协议实例要向外发送的数据帧会由数据链路层放到设备输出队列,再由设备驱动程序的硬件发送函数hard_start_xmit将设备输出队列中的数据帧复制到设备硬件缓冲去,实现对外发送。

Linux内核2.5版本以后在数据链路层实现了一种新的处理输入数据帧的NAPI,除了用struct net_device数据结构描述的网络设备基本属性外,内核还定义了一个新的数据结构 struct napi_struct来管理这类设备的新特性与操作。系统运行时,支持NAPI模式的网络设备在收到数据帧后,该网络设备的struct napi_struct数据结构的实例会放到cpu的 struct softnet_data数据结构的poll_list链表中,网络子系统的接收软件中断被调度执行时,在poll_list链表中的设备的poll方法会被依次调用执行,一次读入设备缓冲去中的多个输入数据帧。

数据帧的接收处理

网络设备收到的数据帧由网络设备驱动程序推送到内核地址空间后,在数据链路层中如何将数据帧放入cpu的输入队列呢?Linux内核网络子系统实现了两种机制:1.netif_rx:这是目前大多数网络设备驱动程序将数据帧复制到SocketBuffer后,调用的数据链路层方法,它通知内核接收到了网络数据帧,标记网络接收软件中断,执行接收数据帧的后续处理,这种机制每接收一个数据帧会产生一个接收中断。2.NAPI:这是内核实现的新街口,在一次中断中可以接收多个网络数据帧,减少了cpu响应中断请求进行中断服务程序与现行程序之间切换所花费的时间。

NAPI

是linux网络子系统中实现的一种提高网络处理效率的技术,它结合中断和轮询两种工作模式,在一次中断后从网络设备中读取多个网络数据包,在高负载的情况下可以获取更好的网络数据处理性能,减轻cpu的负担。它的核心概念是使用中断与轮询相结合的方式来代替纯中断模式,当网络设备从网络上收到数据帧后,向cpu发出中断请求,内核执行设备驱动程序的中断服务程序接收数据帧,在内核处理完前面收到的数据帧前,如果设备又收到新数据帧,这是设备不需要产生新的中断,内核继续读入设备输入缓冲去中的数据帧,直到设备输入缓冲区为空,再重新打开设备中断。这样设备驱动程序同时具有了中断与轮询两种工作模式的优点。1.异步事件通知:当有数据帧到达时用中断通知内核,内核无需不断查询设备的状态。2.如果设备队列中仍有数据,无需浪费时间处理中断通知、程序切换等。

网络设备要利用NAPI工作模式的特性,需要将网络设备驱动程序做升级:增加新的数据结构、实现poll函数、对接收中断处理程序进行修改。

NAPI工作流程

首先网络设备从网络介质上收到网络数据帧后,存入网络设备的硬件缓冲区,然后向cpu发出中断请求,cpu响应设备中断请求后执行接收中断处理程序,网络设备接收中断处理程序将数据复制到内核地址空间的socket Buffer中,最后调用netif_rx_schedule函数

在这里插入图片描述

数据链路层与网络层的接口

网络数据由网络设备驱动程序接收后,从网络设备硬件缓冲区穿过,tcp/ip协议栈最后到达应用程序,每一层的处理都需要确定应该如何将数据帧发送给正确的协议实例。当网络设备驱动程序接收到一个数据帧后,驱动程序将数据帧存放再sk_buff数据结构中,并初始化sk_buff中的protocol。这个数据域中的值可以是定义在内核中的某个协议的标识符,也可以是输入数据帧MAC协议头中的一个数据域。网络设备的硬件类型确定了数据链路层的协议,而且各种类型的网络设备调用自己的驱动程序来接收数据帧。数据链路层的处理程序解析数据链路层的协议头信息,据此判断该数据帧(去掉mac协议头后)应该传给网络层的哪个协议处理程序。

网络层接收到数据帧后,从网络层的协议头中解析该数据帧的传输层使用的协议,确定应将数据帧传给传输层的哪个协议处理程序接收。传输层从自身的协议头信息提取目标端口号,以确定接收数据帧的应用程序。

在linux内核中定义了两个哈希链表,其中的每个元素都是一个struct list_head变量,指向网络层协议的packet_type数据结构类型变量实例,这两个向量表形成了数据链路层与网络层之间接收数据帧的接口。接口向量表:将所有网络设备接口收到的数据包发送给网络层协议;只将与协议标识符相匹配的数据包发送给网络层协议。

3.网络层的传送

网络层协议是tcp/ip协议栈与网络设备驱动程序所管理的硬件发送的连接处,网络数据包经过网络层的处理后,已经包含了所有向外发送需要的信息,比如源地址、目标地址、协议头等,可交由网络设备发送。另外,接收到的网络数据包在网络层确定其进一步发送的路径,是在本机向上传递,还是继续向前发送。数据链路层的驱动程序只关心将上层交给的数据包向外发送,将接收到的数据包向上传递,而网络层协议的关键任务是决定数据包的去向。

网络层在tcp/ip协议栈中处于第3层,linux内核支持许多网络层协议。

在这里插入图片描述

IP协议基本概念

Ip协议的任务:数据包校验和检验、防火墙对数据包过滤、数据分片和重组、接收发送和前送(目的ip地址不是本机,只是经过本地主机继续前送)数据包。网络层ip协议处理函数处理网络数据包的依据是ip协议头。在协议栈中,各层协议都有自己的协议头信息,来描述各层协议需要对数据包作何处理。

ip协议头包含:ip协议版本、协议头长度、数据总包长度,源地址、目的地址等。

ip协议实现前的准备工作

linux内核中任何组件要在系统运行期间被正确的调用执行,首先需要在适当的条件和时间初始化,建立其运行环境并向内核注册,ip协议子系统的初始化是在内核启动期间完成的。

ipv4协议初始化由ip_init函数完成,当在ip层获取数据包后,要完成的最重要的任务是决定如何传递数据,所以ipv4协议初始化的任务就是:初始化路由子系统,建立独立于协议的路由缓冲表。路由表保存了数据包发送的目标或吓一跳的地址信息。初始化管理裸ip的基本功能,如果配置了ip组发送功能,由于组发送功能使用/proc文件系统,所以还要初始化组发送在/proc文件系统的入口。

Ip数据包的前送和本地发送

如果数据包的目的地址不是本机,内核需要把数据包前送给适当的主机,否则就需要将数据包上传给tcp/ip协议栈以上的协议实例。

数据包的前送分为两个阶段完成:ip_forward和ip_forward_finish,第二个函数在第一个函数执行结束时调用。当程序运行到ip_forward函数时,数据包前送需要的信息都已准备好,这些数据包括:数据包前送路径的路由信息。

处理数据包前送的主要步骤:

1.处理ip选项 2.基于ip协议头的数据域确定数据包可以前送 3.对ip协议头的存活时间TTL数据域减一,如果TTL为0,则丢弃

4.基于路由的MTU,如果数据包的长度大于MTU,需要对数据包分片 5.将数据包通过选定的网络接口发送出去。

6.处理错误,如果数据包由于某种错误不能前送,源主机会收到一条icmp的消息描述遇到的问题,当数据包通过另一路由重定向前送时,源主机也会收到一条icmp的消息。

在IP层的发送

数据包在网络层离开本地主机前往另一主机,数据包可以是传输层初始化的本地数据,或者是前送数据包的最后阶段,数据包对外发送阶段在内核的处理任务包括:1.查找下一站点,ip层需要知道完成数据包输出功能的是哪一个网络设备,以及到达下一个站点的路由器。2.初始化ip头,需要填写ip协议头的几个数据域,比如数据包标识符id,还有数据包分片、处理校验和等工作。3.由网络过滤子系统检查数据包。4.更新统计信息。

4.传输层udp协议的实现

udp是不可靠、无连接的数据报协议,不可靠指在udp协议中没有检测到数据是否能够到达网络另一端的机制,在主机内,udp可以保证正确的传输数据。如果要发送的数据量很小,创建连接的开销、保证可靠发送需要做的工作可能比发送数据本身的工作量还要大很多时,udp是一个很好的选择。比如dns域名系统,只有一个请求和相应的回答需要发送,这时建立连接和维护连接的开销太大,使用udp比较合适。udp在协议头中使用一个32位字节来描述数据包发送的源地址和目的地址,其中16位字节描述源端口号,另16字节描述目的端口号。然后udp通过这32位字节的描述将数据传给正确的应用程序。

udp协议实例向上有与套接字层的接口,向下有与网络层(IP层)之间的接口,在完成将应用程序数据复制到内核地址空间后继续向网络层传递,或者从网络层收到的数据包传给正确的应用程序。

发送udp数据报的实现

用户程序在应用层调用socket系统调用,打开一个sock_dgram类型的套接字,在通过套接字接收和发送数据时,数据包会通过udp协议栈向外发送,或者由udp协议上传给套接字到达应用程序。1.初始化一个连接 2.在udp套接字上发送数据包 3.向ip层发送数据包 4.从用户地址空间复制数据到数据报。

udp协议接收的实现

传输层所有协议族的协议实例:tcp,udp都是从网络层ip处接收数据包的,在ip层处理完数据包后,ip层将数据包传递给上层协议的接收函数,传给哪个协议来接收,由IP协议头中的protocol数据域译码得出。根据译码结构作为索引查询哈希链表来确定是哪个协议来接收数据包。如果值为ipproto_udp,则由udp协议处理,有一个函数_udp4_lib_rcv是实际处理来自ip层的所有输入数据包的函数,是处理udp输入数据包的第一个接收函数,实现对接收到的数据包进行正确性检查、地址类型分析(唯一主机地址、组发送或广播地址)、调用相应的函数处理输入过程。udp协议接收广播和组发送数据包:广播和组发送数据包会传给多个目标地址,在同一个主机上就有可能有多个目标端口在等待接收数据包。当udp协议处理广播和组发送数据包时,协议接收函数查看是否有多个打开的套接字要接受该数据包,当输入数据包的路由表入口标志设置了广播和组发送标志时,udp的接受函数就调用udp协议的组接受函数,将数据包分发给所有有效的侦听套接字,函数的处理流程需要遍历udp哈希链表,找到所有接受数据包的套接字。

5.传输层tcp协议的实现

应用层使用传输层的tcp协议来完成数据的可靠传输,因为tcp协议能保证数据完整准确在网络上传送到目标地址。tcp协议特性是提供可靠的、面向连接、字节流传送服务,实现传送的过程为首先在通信双方:客户端与服务器之间提供连接,一个tcp客户与某个给定服务器建立连接,通过建立的连接与服务器交换数据,最后结束连接。

tcp协议使用肯定回答和重传机制来提供可靠数据传送功能,在使用tcp协议传输数据后,发送方要等待接收方回答信息,系统如果没有得到远端系统的回答,tcp自动重传数据并等待更长的时间。如果几次重传不成功,tcp协议放弃重传。tcp协议包含了一个算法来估算数据段在客户端与服务器之间的动态传送时间RTT,以确定要等待多长时间能够收到回答信息。另一方面,在tcp两端协议协作数据交换单位为数据段。每个数据段都有校验和来校验数据是否受损。如果在接受方接收到完好的数据,那么接收方需要向数据发送方返回正确的回答信息。如果数据被损坏,接收方扔掉数据段,在一段时间后,发送数据段的tcp模块重传没有收到接受正确的数据段。tcp数据段格式有16位的源端口号和目标端口号,32位的序列号等等。

tcp协议在两个通信的主机之间建立点到点的逻辑连接,在数据开始传送之前,两个端点之间通过交换握手信息控制信息来建立对话连接,tcp协议在协议头的flag字段设置标志位,来指明当前传送的数据段是控制信息还是负载数据。

tcp建立连接与终止

tcp使用的握手控制信息称为三次握手,在两个端点之间一共要交换3个控制数据段。主机A与主机B建立连接,首先主机A要向主机B发送一个数据段,该数据段设置了同步序列号SYN,这个数据段告诉主机B,主机A要与之建立连接,并告诉B它传送数据的起始序列号,作用是让数据以正确的顺序送达。然后主机B返回主机A一个回答数据段,该数据段设置了回答位ACK和同步位SYN标志。B的回答数据段是A的请求数据段,并通知主机A,B的起始序列号,最后主机A发送收到主机B回答的确认数据段,然后开始传送实际的数据。

在以上的三次握手信息交换后,主机A的tcp实例可以确定远程tcp协议实例启动,并准备好接受数据。一旦建立连接,就可以开始传输数据。当tcp两端交互模块结束数据传送后,它们又将交换三次握手数据段,这些数据段设置了“发送方已经没有数据传送”的结束位标志FIN位来关闭连接。tcp协议提供的是在两个系统之间建立点到点数据交换的逻辑连接。

tcp是以连续字节流的格式交换数据的,而不是独立的数据包。因此tcp协议要维护字节传送的顺序,在tcp协议头中的序列号和回答序列号就是用于跟踪字节传送顺序。为了保证正确跟踪字节流,连接的两端必须知道对方的起始序列号,连接的两端在握手期间,通过交换同步数据段来同步字节数,在握手同步数据段的序列号数据域包含了初始序列号ISN,是传送字节数的起始点,处于安全考虑,它是一个随机数。传送数据的每个字节从ISN开始顺序计数,发送的第一个数据字节序列号是ISN+1。数据段头中的序列号指明了数据段第一个字节在数据流中的顺序位置,比如在数据流第一个字节的序列号是1,ISN=0,有4000个字节已经传送,这时当前段中的第一个字节是4001,序列号也应该是4001.

回答控制数据段有两个功能:确认回答和流控制。确认信息告诉数据发送方已经收到多少字节的数据,接收方还能接受多少字节的数据。tcp协议规范并不要求每个数据包都需要一个独立回答,回答段的序列号是接受到的所有字节数的和。比如第一个发送的字节序列号是4001 ,序列号也应该是4001 .最后tcp协议要负责将从ip接受到的数据传送给正确的应用,与数据绑定的应用由16位的端口号标识。源端口号与目的端口号都包含在tcp的协议中,从应用层正确接受数据和将数据正确发送给应用层,是tcp协议提供的服务中重要部分。

tcp协议实现功能:数据收发、连接管理、流控制管理、回答超时管理。

tcp协议接受过程的实现

tcp协议是Linux网络体系中最复杂的部分,使用了大量算法和外部功能扩展机制来实现协议。为了将数据包传送给传输层正确的协议处理函数,输入数据包使用的传输层协议在ip层处理时已经设定。在传输层,各协议输入处理函数在协议初始化时注册到内核tcp/ip协议栈接口,ip层调用ip_local_deliver函数在ip数据包协议头protocol数据域中设定的值,在传输层与ip层之间管理协议处理接口的哈希链表protocol中查询,找到正确的传输层协议处理函数块,并上传数据包。对应tcp协议,它在protocol结构中初始化的输入数据包处理函数时tcp_v4_rcv,该函数定义在tcp_ipv4.c文件中。

Linux内核中tcp发送功能的实现

tcp协议实现的传送功能是指将从应用层通过打开的套接字写入的数据移入内核,通过tcp/ip协议栈,最终通过网络设备发送到远端接受主机。一旦应用层打开一个套接字,并且发出写数据请求,就会调用tcp协议栈实现的传送例程来处理所有从打开的套接字上传来的写数据请求。tcp传送特点有:异步传送、汇集从套接字传送的数据形成tcp协议的数据段,复制到SocketBuffer、管理和维护SocketBuffer链表,形成SocketBuffer传送队列缓存传送数据,准备以后发送、管理SocketBuffer缓冲区分配,如果队列最后一个SocketBuffer已满,但套接字缓冲区还有新的数据要写入,则分配一个新的SocketBuffer来接受数据。

tcp的time_wait处理

tcp在time_wait状态上等待的时间是数据段最大存活周期MSL的两倍,每个系统对tcp的实现都需要选择一个MSL的值,在RFC规范中建议是2分钟,也就是tcp在time_wait状态上等待的时间为1-4分钟。MSL是任何ip数据包在网络存活的最长时间,对于Ip数据包,在Ip协议头中有一个8位的数据域TTL,是Ip数据报可经过的最大跳数255。TTL是数据包可经过的最大跳数,不是时间的限制值。

数据包丢失常常是因为路由异常引起的,比如一个路由口崩溃了或两个路由之间的链路下线。路由协议需要花几秒或者几分钟的时间来建立稳定路由或者寻找一条新的替换路由。在此期间可能发生路由死循环,也就是A路由器发送数据包给路由器B,路由器B又把它们送给路由器A。同时假设丢失的数据包是tcp数据段,tcp发送超时后会重传同一数据包。重传数据包通过替代路由到达目标地址。随后路由死循环结束,路由异常修复后原路由恢复正常,在以上死循环路由上的数据包最后也送达目标地址,这些原数据包称为丢失复制数据段或者迷失复制段,tcp必须处理这些复制段。

tcp连接需要维护time_wait状态有两个原因:当结束tcp连接时,使连接两端可靠结束、让网络中旧的复制段超时。

第一个原因:假设最后一个ACK数据段丢失,服务器会重传结束连接的FIN数据段,所以客户端必须维护状态信息,以便于重传最后的ACK数据段,服务器接收到客户端的回答数据段会将它作为错误数据包处理。如果tcp在终止一个连接时,tcp要完成所有需要的数据流,才能使断开连接结束的彻底。它必须正确处理终止连接的4个数据段丢失的情况,这也说明了为什么执行活动关闭时tcp仍要在time_wait状态上等待,因为连接的一端可能会重传最后一个ACK数据段。

现在假设在两个端口之间有一个tcp连接,该连接在数据传送后关闭,一段时间后,在同一地址两端建立一个新连接,后一个连接称为前一个连接的化身,因为他们的地址完全相同。tcp必须阻止前一个连接上的旧复制段出现在新的连接化身上。为了处理这种情况,tcp在连接还在time_wait状态上时不会初始化新的连接,化身。因为tcp在time_wait状态上等待的时间是MSL的两倍,它可以在一个MSL期间丢失数据包,在另一个MSL期间扔掉回答。为了强制执行这条规则,我们保证成功建立一个tcp连接后,网络中所有前一个连接的复制段都超时。由此可知一旦tcp连接的一端接收到关闭连接的要求,它必须进入time_wait状态等待一段时间(2倍最大存活周期),最后才终止连接。这有两个重要概念:关闭连接和连接被迫关闭。关闭连接来自于连接一端发出的明确关闭连接要求,但连接被迫关闭是因为tcp收到一个带FIN标志的tcp数据段,所以将tcp连接设置为time_wait状态可以实现防止关闭连接上的数据段与新连接数据段混淆,如果一个已经关闭连接上的数据还在网络上游走,而与前次连接池地址完全相同的一个新连接开始。还可以使连接保持一段时间,这段时间大于数据包重传所需的最长时间,在这段时间里即使最后一个ACK数据包丢失,也有足够的时间重传最后一个ACK。在一个大型服务器中,TCP/IP协议栈要解决的一个重大问题就是:需要维护大量的套接字在time_wait状态所耗费的大量内存资源。Linux内核对time_wait状态的实现,展示了Linux TCP/IP协议栈的体系结构满足成千的打开连接的需要。

在Linux TCp/Ip协议栈中记录了tcp连接、连接状态、接收缓冲区的是struct sock数据结构,struct sock数据结构的每个实例都需要分配内存。在每个服务器上都有大量的连接在不停的打开和关闭,如果使用struct sock数据结构来维护这些等待关闭连接的套接字,那么开销非常大,所以Linux内核使用了另一个数据结构来管理TCP连接的time_wait状态。为了降低对内存的消耗,使用了一个更小的数据结构,而且在数据结构后不跟接收缓冲区,这个数据结构是struct_inet_timewait_sock,定义在inet_timewait_sock.h文件中。

6.套接字层的实现

Linux内核实现的套接字接口,将unix的一切都是文件操作的概念用在网络连接访问上,使应用程序可以用常规文件操作API访问网络连接。TCP/IP协议栈驻留在内核中,与内核的其他组件共享内存,传输层以上执行的网络功能都是在用户地址空间完成的。Linux使用内核套接字概念与用户空间套接字通信,这样使实现和操作更加简单。这些服务向下与内核接口,向上与用户空间接口,应用程序使用这一套API访问内核中的网络功能。

套接字概述

Linux创建的目的使开发一套在功能上与unix系统兼容的操作系统,套接字API是unix应用与网络程序之间最著名的接口,Linux也提供了一个套接字层,在传统unix中实现的几乎所有基于tcp/ip的网络应用都成功移植到了Linux。套接字接口是tcp/ip协议栈中传输层协议的接口,也是传输层以上所有协议的实现。在网络程序功能中是内核与应用层之间的接口。tcp/ip协议栈本身在传输层以上就不包含任何其他协议,Linux替代传输层以上协议实体的是一个标准接口,称为套接字。它实现传输层以上所有的功能。可以说套接字是tcp/ip协议栈对外的接口。在Linux中,在与协议栈交互时,套接字接口是应用程序利用tcp/ip协议栈网络协议的唯一途径。有3个基本功能:传输数据、为tcp管理连接、控制或者调节tcp/ip协议栈的操作。它设计的简单好用,还可以用于Linux内部进程与进程之间通信。

Linux套接字体系结构独立于具体网络协议栈的套接字,可以同时支持多个网络协议栈的工作,也支持Internet协议族的实现过程,任何协议栈都可以在套接字通用体系结构的基础上派生出具有协议族特点的套接字接口。套接字系统调用各功能函数传送到内核套接字功能函数。

7.应用层-网络应用套接字编程

应用程序要访问Linux操作系统内核实现的网络功能,需要应用程序编程接口,也就是套接字编程API。首先启动服务器运行,稍后客户端就可以开始连接服务器,客户端向服务器端发出连接请求,服务器回答客户端的请求,连接建立起来,双方就可以开始交换数据,这个过程一直延续到客户端关闭连接,向服务器端发送关闭连接的通知,随后服务器也关闭连接等待下一次客户连接请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值