Posix API与网络协议栈

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

目录

文章目录

前言

一、TCP三个阶段

1.建立连接

    三次握手

POSIX API 实现

2.传输数据

3.断开连接

二、TCP HEAD

窗口大小(Window Size)

校验和(Checksum):

紧急指针(urgent pointer):

三、UDP

四、TCP状态迁移图

总结


前言

本文主要介绍 Posix API与网络协议栈

对于POSIX的介绍.在《UNIX环境高级编程》中的描述是:

POSIX是一个由 IEEE(电气和电子工程师学会 )制订的标准族。 POSIX的意思是计算机环境
的可移植操作系统界面(Portable Operating System Interface for Computer Environment)。

这边可以理解是为 POSIX 是为Unix操作系统开发制定的一套标准

Posix API包括

1.socket
2.bind
3.listen
4.accept
5.recv
6.send
7.close

8.connect //作为客户端连接服务端时使用

 本专栏知识点是通过零声教育的线上课学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接 C/C++后台高级服务器课程介绍 详细查看课程的服务。


提示:以下是本篇文章正文内容,下面案例可供参考

一、TCP三个阶段

1.建立连接

    三次握手

        

三次握手是发送在哪个函数里面: 当客户端调用connect函数连接 服务端

当客户端第一个次发送SYC到达服务端时, 服务端会构建一个包(结构体: 结构体中包含客户端的信息) 加入队列(半连接队列)中, 当服务端收到客户端的ACK包时,同样也会构建一个队列(全连接队列), 会从半连接队列中找是否有这个客户端的包, 如果有就放到全连接队列中, 这个连接(握手)的节点 叫做 TCP控制块(tcb)

半连接队列:syn queue 

全连接队列:  accept queue

如何通过网络数据包, 查找到半连接队列的节点(TCB)

五元组:(sip(源IP),  dip(目的IP), sport(源端口), dport(目的端口), proto(协议))

端口只有65535个, 如何做到百万级别的连接

一个连接底层就是一个tcb,tcb的唯一性就是五元组, 一个连接对应一个五元,只要五元不冲突就可以依次增加

测试百万连接并发,要开100个端口

从五元组的角度来说 源IP只有1个,目标IP也只有一个,源端口(客户端端口不可被控制只有65535个),那么三个客户端并发请求最多只能支撑3*65535 个连接,于是只能通过增大服务端的端口来使五元组能扩展的更多(如果有足够多的客户端机器(源端口),那么一个目的端口也可以实现百万连接)

POSIX API 实现

1.listen,

在socket fd创建时, 底层会有一个tcb的存在,listen 把tcb设置成listen(被监听 可连接)的状态。(后续全连接队列, 半连接队列创建的前提)

 2.accept

当连接队列为空时, 等待阻塞

 当连接进入全连接队列后, accept 函数产生client fd

clientfd = accept(listenfd, addr, addrlen);

3.connect

fd查找到对应的tcb,通过tcb 对 地址发送syn包

connect(fd, serveraddr, size)

4.bind

socket(插座), 一个socket由两部分组成 fdtcb, 当创建socket 时会产生一个 fd,使用bind 把 fd 跟tcb进行绑定

不会对tcb进行状态改变,此时tcb还是处于closed状态

bind(ip, port)

2.传输数据

     send(): 把数据 copy 到内核(tcb)中,什么时候发送数据到对端,发送多少数据由网络协议栈决定 。通过对端的ACK(确认值)回传,确定对端有没有收到数据。

     recv(): 通过接收过来的包组成五元组 获取到fd,查到对应的tcb 放到recv buff里,应用层调用recv函数读数据,每次读取多少数据由应用程序决定

最大传输单元(Maximum Transmission Unit, MTU):  数据链路层传输的帧大小限制

TCP 最大段大小(Max Segment Size,MSS): TCP 为了避免被发送方分片,会主动把数据分割成小段再交给网络层,最大的分段大小称之为 MSS(MSS = MTU - IP header头大小 - TCP 头大小)

3.断开连接

   close : 将首部标志状态位 FIN 置为 1

   shutdown: 单向的socket便称为半开放Socket, 要实现半开放式,需要用到shutdown()函数

四次挥手:  从下图看 SERVER B 收到 SERVER A的关闭连接请求后, 把ACK 跟 FIN 分开发送, 因为延迟确认的存在, 第二步的ACK跟第三步的FIN包 经常会合在一起发送给对端(三次挥手)

当 SERVER A 收到 SERVER B 的 FIN 以后, 只能确认SERVER B 不会再发送数据给自己了,但是自己这个时候还是可以发送数据给 SERVER B,这个时候的状态也叫 FINWAIT_1

当 SERVER A 收到 SERVER B 的 FIN 以后回传给 SERVER B 确认ACK包,表示我已经收到这个FIN包了,同时自己进入了 CLOSING 状态中

等待 SERVER A 给自己发 自己FIN包 的 ACK(确保对面知道自己要关闭连接了),如果收到以后就会进入TIME-WAT

在TIME-WAIT 状态持续 2*MSL后 关闭连接

二、TCP HEAD

tcp的每次交互都会携带一个 head 头,了解TCP head 的组成可以加深对TCP协议的了解

在T C P首部中有 6个标志比特, 它们中的多个可同时被设置为 1

URG:  紧急指针( 这个值置为1时 , urgent pointer)有效。
ACK:  确认序号有效(这个值置为1时 ,Sequence number有效)。
PSH : 接收方应该尽快将这个报文段交给应用层。
RST : 重建连接。
SYN : 同步序号用来发起一个连接。
FIN : 发端完成发送任务。

序列号(Sequence number): 单位字节数 byte

确认号(ACKnowledgment number): 单位字节数 byte

窗口大小(Window Size)

校验和(Checksum):

紧急指针(urgent pointer):

三、UDP

往内核添加数据(hello)

memcpy(buffer, "hello", strlen("hello"))

1.sendto(buffer)

udp:  ethdr(以太坊头) + iphdr(ip头)+ udphdr(udp头) +"hello"

udphdr(udp头) 包含: sport(源端口号), dport(目标端口号), length(长度),  crc(校验值)

四、TCP状态迁移图

状态迁移流程:


总结


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值