TCP 和 UDP 的 Socket 调用

2023-11-16

在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设置为 AF_INET 和 AF_INET6。另外,还要指定到底是 TCP 还是 UDP。TCP 协议是基于数据流的,所以设置为 SOCK_STREAM,而 UDP 是基于数据报的,因而设置为 SOCK_DGRAM。

TCP 的服务端要先监听一个端口,一般是先调用 bind 函数,给这个 Socket 赋予一个 IP 地址和端口。为什么需要端口呢?要知道,你写的是一个应用程序,当一个网络包来的时候,内核要通过 TCP 头里面的这个端口,来找到你这个应用程序,把包给你。为什么要 IP 地址呢?有时候,一台机器会有多个网卡,也就会有多个 IP 地址,你可以选择监听所有的网卡,也可以选择监听一个网卡,这样,只有发给这个网卡的包,才会给你。

当服务端有了 IP 和端口号,就可以调用 listen 函数进行监听。在 TCP 的状态图里面,有一个 listen 状态,当调用这个函数之后,服务端就进入了这个状态,这个时候客户端就可以发起连接了。

在内核中,为每个 Socket 维护两个队列。一个是已经建立了连接的队列,这时候连接三次握手已经完毕,处于 established 状态;一个是还没有完全建立连接的队列,这个时候三次握手还没完成,处于 syn_rcvd 的状态。

接下来,服务端调用 accept 函数,拿出一个已经完成的连接进行处理。如果还没有完成,就要等着。

在服务端等待的时候,客户端可以通过 connect 函数发起连接。先在参数中指明要连接的 IP 地址和端口号,然后开始发起三次握手。内核会给客户端分配一个临时的端口。一旦握手成功,服务端的 accept 就会返回另一个 Socket。

监听的 Socket 和真正用来传数据的 Socket 是两个,一个叫作监听 Socket,一个叫作已连接 Socket

连接建立成功之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

基于 TCP 协议的 Socket 程序函数调用过程。

说 TCP 的 Socket 就是一个文件流,是非常准确的。因为,Socket 在 Linux 中就是以文件的形式存在的。除此之外,还存在文件描述符。写入和读出,也是通过文件描述符。

在内核中,Socket 是一个文件,那对应就有文件描述符。每一个进程都有一个数据结构 task_struct,里面指向一个文件描述符数组,来列出这个进程打开的所有文件的文件描述符。文件描述符是一个整数,是这个数组的下标。

UDP 是没有连接的,所以不需要三次握手,也就不需要调用 listen 和 connect,但是,UDP 的交互仍然需要 IP 和端口号,因而也需要 bind。UDP 是没有维护连接状态的,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,都调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。

最大 TCP 连接数 = 客户端 IP 数×客户端端口数。对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。

当然,服务端最大并发 TCP 连接数远不能达到理论上限。首先主要是文件描述符限制,按照上面的原理,Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目;另一个限制是内存,按上面的数据结构,每个 TCP 连接都要占用一定内存,操作系统是有限的。

1、多进程方式

这就相当于你是一个代理,在那里监听来的请求。一旦建立了一个连接,就会有一个已连接 Socket,这时候你可以创建一个子进程,然后将基于已连接 Socket 的交互交给这个新的子进程来做。

2、多线程方式

在 Linux 下,通过 pthread_create 创建一个线程,也是调用 do_fork。不同的是,虽然新的线程在 task 列表会新创建一项,但是很多资源,例如文件描述符列表、进程空间,还是共享的,只不过多了一个引用而已。

有个 C10K,它的意思是一台机器要维护 1 万个连接,就要创建 1 万个进程或者线程,那么操作系统是无法承受的。如果维持 1 亿用户在线需要 10 万台服务器,成本也太高了。

3、IO 多路复用,一个线程维护多个 Socket

由于 Socket 是文件描述符,因而某个线程盯的所有的 Socket,都放在一个文件描述符集合 fd_set 中,这就是项目进度墙,然后调用 select 函数来监听文件描述符集合是否有变化。一旦有变化,就会依次查看每个文件描述符。

4、IO 多路复用,从“派人盯着”到“有事通知”

能完成这件事情的函数叫 epoll,它在内核中的实现不是通过轮询的方式,而是通过注册 callback 函数的方式,当某个文件描述符发送变化的时候,就会主动通知。

这种通知方式使得监听的 Socket 数据增加的时候,效率不会大幅度降低,能够同时监听的 Socket 的数目也非常的多了。上限就为系统定义的、进程打开的最大文件描述符个数。因而,epoll 被称为解决 C10K 问题的利器。

此文章为9月Day13学习笔记,内容来源于极客时间《趣谈网络协议》,推荐该课程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP 和 UDP 的 Socket 调用 的相关文章

  • 数据库的url配置8.0

    spring datasource username root spring datasource password lhh12345 spring datasource url jdbc mysql localhost 3306 myba

随机推荐

  • numpy.diag()结构及用法

    numpy diag v k 0 官方文档 以一维数组的形式返回方阵的对角线 或非对角线 元素 或将一维数组转换成方阵 非对角线元素为0 两种功能角色转变取决于输入的v 1 更深层的见numpy diagnal 参数详解 v array l
  • windows获取系统DPI

    dc GetDeviceCaps LOGPIXELSX 每英寸水平逻辑像素数 dc GetDeviceCaps LOGPIXELSY 每英寸垂直逻辑像素数 dc GetDeviceCaps HORZRES 水平像素总数 dc GetDevi
  • [Java]获取java方法注释实例

    Method methods company class getMethod getId null PK pk methods getAnnotation PK class System out println pk
  • vue指令中v-show和v-if以及keep-alive的区别

    v if 属于条件显示 满足条件就显示元素 不满足就删除元素 通过操作DOM元素完成 v if的首次渲染显示的开销较小 因为它只渲染满足条件的那一个元素 切换组件时 其开销较大 因为它每切换以此就要重新触发生命周期渲染显示新元素 v if值
  • JS实现轮播图(自动+手动)

    网页轮播图效果 核心原理 tips 代码在文章末尾 这个ul就是我们这四张图片的父盒子 我们通过对这个父盒子添加动画函数来实现移动 然后给父盒子来一个溢出隐藏就达到了轮播的效果 动画函数如下 function animate obj tar
  • 【python爬虫】8.温故而知新

    文章目录 前言 回顾前路 代码实现 体验代码 功能拆解 获取数据 解析提取数据 存储数据 程序实现与总结 前言 Hello又见面了 上一关我们学习了爬虫数据的存储 并成功将QQ音乐周杰伦歌曲信息的数据存储进了csv文件和excel文件 学到
  • 8.typescript-函数的类型

    今儿个甚是乏累呢 但是 lt 下面可能是正题儿 gt 1 函数声明 1 function student x string y number string 2 return 我是 x 今年 y 岁 3 4 5 console log stu
  • 商品期货怎么玩? 1手交易需要多少钱?

    期货市场中有许多大宗商品 把他们统称为商品期货 近几年我国商品期货品种不时在增加 固然期货风险比较高 但收益也十分可观 而且商品期货开户几乎没有门槛 国内商品期货免费开户 无资金限制 凭身份证和银行卡即可办理 开设期货帐户 能在网上开期货帐
  • Unity XCode iOS 实现拍照和相册选择上传头像

    显示弹窗 通过UIAlertController来创建一个弹窗 if defined cplusplus extern C endif 导出接口供unity使用 void IOS Open IOSCameraController app I
  • 剑指 Offer 25. 合并两个排序的链表(java+python)

    输入两个递增排序的链表 合并这两个链表并使新链表中的节点仍然是递增排序的 示例1 输入 1 gt 2 gt 4 1 gt 3 gt 4 输出 1 gt 1 gt 2 gt 3 gt 4 gt 4 限制 0 lt 链表长度 lt 1000 思
  • sql语句学习(b站韩顺平的demo)

    表的CRUD varchar varchar2 char的区别 时间 时间戳使用 创建表 创建一张表 表结构与已经存在的表一致 查看表的信息 表中增加一列 修改表中的列 删除表中的列 修改表名 修改表的字符集 修改表中的列名 表中数据的插入
  • 关于算法,我们都应知道的

    定义 算法是指对特定问题求解步骤的一种描述 特性 1 有穷性 算法是由若干条指令组成的有穷序列 总是在执行若干次后结束 不可能永不停止 2 确定性 每条语句有确定的含义 无歧义 3 可行性 算法在当前环境条件下可以通过有限次运算实现 4 输
  • JavaEE学习记录day09集合03 Map集合、Stream流

    JavaEE学习记录day09集合03 Map集合 Stream流 1 Map集合 1 1Map集合概述和特点 理解 Map集合概述 interface Map
  • 看书标记【R语言数据分析与挖掘实战】5

    第五章 挖掘模型 5 1 分类预测 回归分析 回归分析是确定预测属性 数值型 与其他变量间相互依赖的定量 关系的最常用的统计学方法 包括线性回归 非线性回归 Logistic回归 因变量有0 1两种取值 岭回归 自变量间有多重共线性 主成分
  • JavaScript引擎,V8引擎的原理

    为什么需要JavaScript引擎 高级的编程语言都是需要转成最终的机器指令来执行 我们所编写的js无论h是交给浏览器或者node执行 最后都是需要被CPU执行的 CPU只认识自己的指令集 机器语言 才能被CPU所执行 所以我们需要js引擎
  • 关于ngx_rtmp_hls_append_sps_pps造成的hls: error appenging SPS/PPS NALs错误

    关于ngx rtmp hls append sps pps造成的hls error appenging SPS PPS NALs错误 一giao我哩giao 今天在调试同rtmp配合nginx推流的时候 发现推live可以推成功 结果在推h
  • 多因素认证与身份验证:分析不同类型的多因素认证方法,介绍如何在访问控制中使用身份验证以增强安全性

    随着数字化时代的到来 信息安全问题变得愈发重要 在网络世界中 用户的身份往往是保护敏感数据和系统免受未经授权访问的第一道防线 单一的密码已经不再足够 多因素认证 MFA 应运而生 成为提升身份验证安全性的重要工具之一 本文将深入探讨不同类型
  • rpm常用命令记录

    文章目录 1 常用rpm命令 2 rpm参数 1 常用rpm命令 rpm ivh xxx rpm 安装rpm rpm Uvh xxx rpm 升级rpm rpm e xxx rpm 删除rpm rpm qi xxx rpm 查看安装包的信息
  • node.js 数据实现分页问题(后端)

    最近在写项目时 碰到的问题 let arr let rows for let e 0 e
  • TCP 和 UDP 的 Socket 调用

    在网络层 Socket 函数需要指定到底是 IPv4 还是 IPv6 分别对应设置为 AF INET 和 AF INET6 另外 还要指定到底是 TCP 还是 UDP TCP 协议是基于数据流的 所以设置为 SOCK STREAM 而 UD