三次握手与四次挥手在具体函数上的体现

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 三次握手与四次挥手在具体函数上的体现


网络编程 API组成

服务端API 客户端API
socket() socket()
bind() bind() [optional]
listen()
accept() connect()
recv()
send() send()
close() recv()
close()
shutdown()

三次握手服务器和客户端分别是发生在哪个函数

  • 服务器调用listen使服务器处于LISTEN状态,等待客户端请求连接
  • 首先客户端调用connect发起第一次SYN包,然后处于**SYN_SENT状态**,此时服务端会将这个连接放进半连接队列
  • 服务端收到SYN包以后会发送给客户端一个ACK|SYN包,此时服务端状态转移为SYN_RECV
  • 客户端接收到服务端发来的ACK|SYN包进行解析后会在半连接队列中查找携带这个信息的节点是否存在,如果存在则move出来加入全连接队列中,并且发送ACK包给服务端,此时客户端状态转移为ESTABLISHED
  • 服务端收到客户端的ack后也状态转移为ESTABLISHED

知识点:

半连接队列与全连接队列

  • 都是在服务端那里存在的队列

backlog参数的含义

  • 三种说法都存在
  • 半连接队列大小
  • 两个队列大小的和
  • 全连接队列大小
  • 本机上man listen查看
    defines the maximum length to which the pending connections for sockfd for sockfd may grow
    代表全连接队列的大小

ddos攻击

  • 客户端只发第一次握手,不会返回ACK,使半连接队列溢出

双方都发起第一次握手可以吗

  • 不可以,会导致连接无法正常建立

数据传输阶段

send返回整数不一定代表发送成功

  • send只是将数据拷贝到了内核,之后多久发送是协议栈规定的,自己不知道

为什么会发生发送不成功?

  • 据包在传输过程中很复杂,可能对方网络很差,在某一个路由器中丢包了,数据包总是根据目的ip、port来寻找

传输过程中的粘包分包问题

客户端调用sendsend只将数据拷贝到协议栈里面,其他什么都不做

如何做好分包粘包

  • 多次send会发生粘包和合包的问题
  • 解决
  • 应用层协议头前面加packetlen
  • 为每一个包加上分隔符 \r\n
  • 这两种做法有什么区别
// 先读长度,再读数据
read(tcphdr, 2);
read(tcphdr->length);
//or
while(count <tcphdr->length){
    size = read(tcphdr->lenghth - count);
    count += size;
}
// 检测内容
read(buffer, 1024);
buffer[idx] = "\r\n";
pkt = &buffer[idx + 2];  // 为了后续合包

网线断了立马重启,tcp是如何检测到的

  • 通过设计->心跳包来检测

网络断开连接

不分客户端或者服务器,只分主动或者被动

  • 首先调用close的端会将最后一次包的FIN位置为1,并且处于状态为FIN_WAIT1
  • 对端收到带有FIN的包后会返回给发送端一个ACK包,这个是立即发送的,代表我知道你不给我发数据了,之后对端状态转移为CLOSE_WAIT
  • 发送端接收到后状态转移为FIN_WAIT2
  • 之后对端在发送FIN包之前的这一段时间,它还可以给发送端发数据,当对端处理好所有数据后会发送最后的FIN包,此时状态会转移为LAST_ACK
  • 发送端接收到对端发送的FIN包之后会发送一个ACK包然后处于**TIME_WAIT状态**,过了这段时间后就处于**CLOSE状态**
  • 对端接收到ACK后连接断开,处于CLOSE状态

一些面试题:

  • 如果出现大量close_wait该怎么办(这种现象是因为recv返回0后到调用close时间太长)
  • 把业务数据释放与网路层的(recvclose)做一个分离,把他做成异步的,就是将释放资源客户端相关做成异步,这样一来recv==0后就可以立即close(fd)
  • 会出现双方同时调用close吗?引入closing
  • 以某一端为例,先发fin,进入fin_wait1,然后收到对端发送的fin包而不是ack,则为两端同时关闭,直接进入closing状态
  • 为什么会有time_wait
  • 如果laskack在传输过程中丢了,则对端会重发fin,如果没有time_wait则对应的端口会立即被释放出来,如果此时有一个应用程序连接进来刚好用到了该端口,则会直接收到fin包从而进入close_wait状态从而直接进入四次挥手
  • 为了避免最后一次ack丢失

简单总结各个函数的作用

socket

  • 文件系统分配fd,且分配一个tcb

bind

  • 绑定本地的ip、端口

listen

  • fd置为listen状态

accept

  • 从全连接队列中取出一个tcb(TCP control block)
  • 并分配一个fd

recv

  • 在对应的fd里面,将对应的readbuffer读出来

send

  • fd对应的tcb里面将数据拷贝到sendbuffer里面

close

  • sendbuffer里面的最后一个包的fin位置为1
  • 回收fd

客户端

bind

  • 可选,如果不调用则随机端口,调用则指定端口

connect

  • 准备一个syn包给服务端发送过去
  • 等待三次握手完成之后connect再返回
  • 思考:这个函数有没有等待的动作,是不是个阻塞的,如果连不上,会阻塞吗
  • 有等待的动作但不会阻塞,如果连不上则会被连接被拒绝
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
前端开发 网络协议 JavaScript
|
2月前
|
网络协议 网络架构
|
3月前
|
网络协议
TCP三次握手和四次挥手
TCP三次握手和四次挥手
|
3月前
|
网络协议 网络架构
三次握手与四次挥手
三次握手与四次挥手
|
3月前
|
网络协议 算法
TCP 三次握手和四次挥手
TCP 三次握手和四次挥手
51 0
TCP 三次握手和四次挥手
|
3月前
|
网络协议 安全
三次握手和四次握手到底有啥区别?
三次握手和四次握手到底有啥区别?
52 0
|
3月前
|
网络协议
理解三次握手与四次挥手
理解三次握手与四次挥手
29 0
|
网络协议
TCP三次握手与四次挥手
TCP三次握手与四次挥手
151 0
|
网络协议
TCP的三次握手与四次挥手
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务端保存的一份关于对方的信息,如ip地址、端口号等。TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:连接、数据传输、退出(关闭)。通过三次握手建立一个链接,通过四次挥手来关闭一个连接。当一个连接被建立或被终止时,交换的报文段只包含TCP头部,而没有数据。
|
网络协议
三次握手-四次挥手
三次握手-四次挥手
105 0