做网站的不足 心得,软文发稿网,禹州做网站,虚拟商品交易网站建设本文介绍linux中与tcp网络通信相关的POSIX API#xff0c;在每次调用的时候#xff0c;网络协议栈会进行的操作与记录。 
POSIX API 
Posix API#xff0c;提供了统一的接口#xff0c;使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动#xff0c;比…本文介绍linux中与tcp网络通信相关的POSIX API在每次调用的时候网络协议栈会进行的操作与记录。 
POSIX API 
Posix API提供了统一的接口使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动比如打开文件所调用的函数是不同的。系统1调用的是open1函数系统2调用的是open2函数在Posix API中统一规定把这个功能的函数包装成open那么当应用程序在不同的系统上调用open函数的时候就都能打开文件了。 
应用程序可能会有自己的打开文件函数比如popenfopen等等都是在直接或间接的调用open。 
网络协议栈 
网络协议栈是内核的一部分是一系列网络协议的集合。负责网络通信和网络数据传输。 
tcp网络通信相关的POSIX API 
socket 
socket通俗的翻译是插座插座分为插头和座socket函数实际上是实现了网络通信中建立连接所需要的“插头”和“座”。在网络通信中“插头”对应着socketfd“座”对应着tcp控制块。 
socketfd存在于用户空间中Tcp协议是网络协议栈的一部分tcp控制块又是tcp协议的一部分。 
Tcp控制块包含了以下内容源IP地址和源端口、目标IP地址和目标端口、连接状态、序列号和确认号、窗口大小、拥塞控制参数、超时和重传信息、接收和发送缓冲区、计时器、选项和标志。 
bind 
给socetkfd的tcp控制块的目的IP地址和目的端口赋值。有些客户端不绑定一个特定的端口那么系统就会随机分配。 
listen与connect 
Listen函数的第二个参数是在设置syn_queue与accept_queue的总长度。listen函数主要在做两件事: 
a.修改tcp控制块的连接状态发生连接前后分别是LISTEN状态和ESTABLISH状态。 
b.建立syn_queue同步队列和accept_queue接受队列。syn_queue用于存储未完成的三次握手的连接请求控制块accept_queue用于存储刚刚完成了3次握手的连接请求控制块等待移交给accept函数进行处理。 
三次握手介绍 
客户端连接到服务器需要首先进行三次握手这三次握手是在底层进行的。服务器在listen状态客户端调用connect之后就在进行三次握手了整个过程对于用户是黑箱的。作为高水平程序员我们还是需要来了解下底层到底是怎么样的运作机制。 
首先了解tcp头需要重点了解的是控制位Flags包括了8块内容CWR、ECE、URG、ACK、PSH、RST、SYN、FIN这些内容位要么填1要么填0用于控制和标识TCP连接的状态和行为。比如客户端发起了第一次握手会往服务器发送一个tcp包这个包会包含包头和没有数据的包体包括后面的两次握手也是这时候SYN被设置为1说明是第一次握手。 三次握手的流程如图所示以下的一根蓝线代表一次握手 第一次握手发送一个tcp包这个包包头的SYN位置被设为1seqnum被随机生成比如是12345由客户端发送给服务器。请求进入到了服务器的syn队列中随即建立相应的请求控制块。 
第二次握手服务器返回一个包这个包包头的SYN和ACK被设为1客户端发送的12345的seqnum收到12345的acknum。服务器也随机生成了一个seqnum比如34531。 
第三次握手客户端发送了一个tcp包于是服务器发送的是34531的seqnum收到的34532的acknum。收到多大的acknum表示seqnum小于这个acknum的tcp包都已经全部被对端接收过了。相应的请求控制块从syn队列移动到accept队列中。 
通过seqnum和acknum的数值排序可以实现tcp通信的不重复、不乱序、不缺失。 
3个问题 
连接的生命周期是什么时候开始的从服务器第一次接收到tcp包开始。第三次握手结束accept队列是如何从syn队列中找到对应的请求控制块的根据源ip和源port查找。Syn泛洪是什么是一种网络攻击手段简单来说就是黑客不断地通过第一次握手并且不回应第二次握手把syn队列塞满导致服务器无法建立新的连接。目前已经通过堡垒机、防火墙等手段拦截了该手段。 
accept 
Accept函数做了两件事 
a.     根据取出的连接请求控制块建立新的fd也就是通常新的clientfd。 
b.     为这个新的fd建立新的tcp控制块。 
send与write 
tcp通信的这两个函数其实只做一件事就是把数据从应用层appliacation拷贝进入内核kenerl的发送缓冲区中。至于内核什么时候把数据发送到对端就不一定了有可能是先凑满一定的字符数再一起发送有可能是看到一定时间内都没有数据再拷贝进入就发送不同的系统会有不同的操作。我们可以通过ifconfig命令查看mtu也就是单个数据包中可以传输的最大字节数。 
recv和read 
tcp通信的这两个函数其实也只做了一件事就是把数据从内核的接收缓冲区拷贝到应用层。 
close 
该函数是负责断开客户端与服务器之间的连接。底层的流程通常称为“四次挥手”。不同于发起连接只能由客户端发起断开连接可以由任意一方启动只分为主动方和被动方。 
Close函数做了两部分工作a.回收fd。b.发送一个控制位FIN为1的包第一次挥手也叫fin包或final包这个包的包体没有任何内容于是对端的recv会返回0。 
当对端接收到FIN包之后通常会返回一个ack包再调用close函数返回一个fin包第二、三次挥手。本端收到fin包之后再返回一个ack包第四次挥手。 
下图是close主动方与被动方的挥手关系与状态变化 红圈对应着主动方与被动方的状态变化。