网络协议栈5:connect()函数之前
我们的应用程序在调用了socket()函数,bind()函数之后,只是在本地创建了socket结构体,sock结构体,并把socket,sock这两个结构体跟I节点,文件句柄结合起来,在把socket创建时所指定的协议的操作集关联到sock结构体上,用于在socket指定了协议之后,使用这个操作集来完成相关的操作;之后的bind()函数则把本地的一个未被使用的端口号(一般大于1024,因为0~1024是知名端口号,保留下来做已知的特定用途,如端口号不是营养程序指定的,则查找空闲的端口号比较烦),用于表示当前sock所属的进程,并把本地的IP跟绑定到sock上,用于表示数据将从哪里被发送到网络上。
所有这些,都只是在本地完成的,都还没有涉及到诸如传输层、网络层、链路层这些网络协议栈的东西,也没有出现TCP/IP/MAC等的数据,因此,socket/bind两个函数的调用,实际上都只是做一些准备的动作,为创建连接这个动作做好基础工作,即为connect函数的登场准备了舞台
Connect函数则是会创建一个SYN数据,发送到远端的IP(connect函数参数指定),寻求握手,建立链接,此时的SYN信号,就会被TCP/IP/MAC三个数据结构的打包,经过传输层,网络层,链路层直到网路上,传给远端地址,然后在本地等待远端地址的回传信息,一旦远端地址侦听并接收到SYN信号,就会创建一个新的进程,之后进程也会创建一个socket,sock等结构体,并把回复的ACK信号经过TCP/IP/MAC三个数据结构的打包,再经过远端的传输层,网络层,链路层传输到远端的网卡上,由远端的网卡发送数据到网路上,因为远端传输的数据的IP地址为本地的IP,经过ARP就能在网络上找到本地的网卡的MAC,进而找到网卡,进而把数据发送到本地端,本地端收到ACK信号后,再回复一个收到ACK信号的信号给远端,则一条链路就建立成功了,如图<tcp三次握手>,以后的数据就都在这条链路上进行传输,而中间经过的路由,则有可能不尽相同,但是两个端点是不变的,其形式大致如图 <网路路由>,因为中间的路由是随时根据网路的情况而调整的,使用ARP技术来达到的。