TCP/IP socket
## TCP Socket
收发缓冲区:
每个socket在linux内核中都有一个发送缓冲区和一个接收缓冲区。
只要对端将数据发送过来,linux内核TCP/IP协议栈就会负责将数据缓存到socket对应的接收缓冲区中,无论是否调用recv。
recv()所做的工作,只是把内核缓冲区中的数据拷贝到应用层用户的buffer里面。
调用send()发送的数据的时候,只是将应用层buffer中数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回(注意:数据是否发送过去不一定)。
linux内核TCP/IP协议栈负责将数据发送到对端。
异常场景:
应用进程一直没有读取数据,导致接受缓冲区满了。此时接收端通知发送端,接收窗口关闭,保证接收缓冲区不会溢出。(TCP流控机制 滑动窗口法)
socket内核发送缓冲区的默认大小 (16KB)
cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4161536
## Errors:socket层标准错误
These are some standard errors generated by the socket layer.
EAGAIN or EWOULDBLOCK: socket被标记为非阻塞,当recv操作阻塞或者接收超时。
The socket is marked nonblocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.
EBADF: 无效socket
The argument sockfd is an invalid descriptor.
ECONNREFUSED: 远程主机拒绝网络连接
A remote host refused to allow the network connection (typically because it is not running the requested service).
EFAULT: 内存越界
The receive buffer pointer(s) point outside the process's address space.
EINTR: 被信号打断
The receive was interrupted by delivery of a signal before any data were available; see signal(7).
EINVAL: 参数无效
Invalid argument passed.
ENOTCONN: 没有建连的socket
The socket is associated with a connection-oriented protocol and has not been connected.
## 1: socket
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
domain : AF_UNIX--本地socket
AF_INET--ipv4
AF_INET--ipv6
type: SOCKT_STREAM--TCP
SOCKT_DGRAM—UDP
## 2: socket reuse (ip复用 或者port复用)
一个socket的五元组:
{<protocol>, <src addr>, <src port>, <dest addr>, <dest port>}
(1) non-reuse
如果指定src addr为0.0.0.0,将不再表示某一个具体的地址,而是表示本地的所有的可用地址。
指定src addr为0.0.0.0,将不再表示某一个具体的地址,而是表示本地的所有的可用地址。
reuse有三个级别:
non-reuse: (src addr,src port)不能冲突。eg: ip1:port1和ip2:port1不冲突。0.0.0.0:port1和ip1:port1冲突。
0.0.0.0和其他IP冲突。
reuse-addr: (src addr,src port)不能冲突。 eg: ip1:port1和ip2:port1不冲突。0.0.0.0:port1和ip1:port1不冲突。
0.0.0.0和其他IP不冲突。
reuse-port: (src addr,src port)可以冲突。eg: 0.0.0.0:port1和0.0.0.0:port1不冲突。
## 使用setsockopt()设置复用。
设置reuse-addr:
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
设置reuse-port:
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int));
## 3: recv
定义:
The recv() function is normally used only on a connected socket
原理:
recv只是将socket对应的接收缓冲区的数据copy到buffer中,真正的是Linux内核的TCP/IP网络协议栈负责接收数据。
接口:
#include <sys/socket.h>
ssize_t recv(int socket, void *buffer, size_t length, int flags);
参数:socket:
buffer: 缓冲区。
length: buffer的长度
flags: 一般设置为0.
返回值:>0: 返回接收的字节数 -1:发生错误 0:对端关闭了连接 (无论阻塞还是非阻塞,返回值的都是这3钟)
These calls return the number of bytes received, or -1 if an error occurred。
For TCP sockets, the return value 0 means the peer has closed its half side of the connection.
阻塞与非阻塞:
阻塞: 默认为阻塞。没有数据时,recv函数将一直等待获取到数据,或者发生报错。
非阻塞: 没有数据时,不会阻塞着读数据,而是返回-1(需要判断errno),需要循环读取数据。
在返回值处理上:
阻塞: 缓冲区有数据,成功执行返回接收到的字节数(>0)。
另一端关闭(=0)。
缓冲区无数据,阻塞一直等。
连接失败(-1), errno = ENOCONN。
非阻塞:缓冲区有数据,成功执行返回接收到的字节数 (>0)。
另一端关闭(=0).
缓冲区无数据,立即返回, 返回值为-1, 同时errno = EAGAIN || EWOULDBLOCK。
连接失败(-1), errno = ENOCONN。
## 4: 设置阻塞方式
(1) sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
或者
(2) int flag = fcntl(sock, F_F_GETFL);fcntl(sock, F_SETFL, flag | O_NONBLOCK);
## 5: connect
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
connect: 默认为阻塞式的。
非阻塞connect实现机制:
a: 创建socket,利用fcntl将其设置为非阻塞。
b: 调用connect函数,如果返回0,则连接建立;如果返回-1,检查errno ,如果值为 EINPROGRESS,则连接正在建立。如果值不是EINPROGRESS,建连错误。
c: 调用阻塞式接口select/pool检测是否连接建立。这里对于select/pool可以采用设置超时时间来等待。
d: 在select/pool的超时时间内成功建立,返回成功建连。否则调用getsockopt获取错误信息。
示例:
https://blog.csdn.net/qq_43684922/article/details/106444292?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-106444292-blog-119000780.235^v27^pc_relevant_t0_download&spm=1001.2101.3001.4242.1&utm_relevant_index=3
## send
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
返回值: > 0 发送的的数据字节数。 -1发送发生错误, 查看errno。=0 N/A
Return Value
On success, these calls return the number of characters sent.
On error, -1 is returned, and errno is set appropriately.
阻塞与非阻塞:
在阻塞模式下,send函数的过程是将应用程序请求发送的数据拷贝到内核发送缓存中,待发送数据完全被拷贝到内核发送缓存区中才返回,当然如果内核发送缓存区一直没有空间能容纳待发送的数据,则一直阻塞。
When the message does not fit into the send buffer of the socket, send() normally blocks。
(1)如果内核发送缓冲区可用大小为0,send()直接堵塞
(2)如果内核发送缓冲区可用空间小于待发送的数据长度len,则send()函数会先把部分数据拷贝到内核发送缓冲区中,然后会阻塞等待有空间,再将剩余数据发送到内核缓冲区。
(3)如果待发送数据的长度大于s的内核发送缓冲区的长度时,会先将s(发送端)的内核发送缓冲区填满,然后发送端会将内核发送缓冲区的数据发送到接收端socket的内核接收缓冲区,所以s(发送端)的内核发送缓冲区又会慢慢腾出空间,send又会将待发送数据往s(发送端)的内核发送缓冲区中copy。
在非阻塞模式下,send函数的过程也是将应用程序请求发送的数据拷贝内核发送缓存中。
send函数不需要等到待发送数据完全被拷贝到内核发送区中才返回。
如果内核缓存区可用空间不够容纳所有待发送数据,则尽能力的拷贝,返回成功拷贝的大小;
如果缓存区可用空间为0,则返回-1,同时设置errno为EAGAIN.
In nonblocking mode it would fail with the error EAGAIN or EWOULDBLOCK in this case. The select(2) call may be used to determine when it is possible to send more data.
errno:
EBADF 参数s 非合法的socket处理代码。
EFAULT 参数中有一指针指向无法存取的内存空间
ENOTSOCK 参数s为一文件描述词,非socket。
EINTR 被信号所中断。
EAGAIN 此操作会令进程阻断,但参数s的socket为不可阻断。
ENOBUFS 系统的缓冲内存不足
ENOMEM 核心内存不足
EINVAL 传给系统调用的参数不正确
相关文章:
TCP/IP socket
## TCP Socket 收发缓冲区: 每个socket在linux内核中都有一个发送缓冲区和一个接收缓冲区。 只要对端将数据发送过来,linux内核TCP/IP协议栈就会负责将数据缓存到socket对应的接收缓冲区中,无论是否调用recv。 recv()所做的工作,只是把内核缓…...

“工作三年,跳槽要求涨薪50%”,合理吗?
如果问在TI行业涨工资最快的方式是什么?回答最多的一定是:跳槽!前段时间,知乎上这样一条帖子引发了不少IT圈子的朋友的讨论 ,有网友提问 “程序员跳槽要求涨薪50%过分吗?”截图来源于知乎,如侵删…...
Vue学习计划九:了解Vue动画效果以及过渡动画和动态组件的使用方法
Vue.js 是一个流行的 JavaScript 框架,它提供了很多工具和功能,可以帮助开发人员创建动态、交互式的 Web 应用程序。其中之一就是动画效果,Vue.js 提供了一系列的 API 和指令,使得添加动画效果变得非常容易。 在 Vue.js 中&#…...

【Linux】进程理解与学习Ⅲ-环境变量
环境:centos7.6,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹相关文章推荐:【Linux】冯.诺依曼体系结构与操作系统【Linux】进程理解与学习Ⅰ-进程概念浅谈Linux下的shell--BASH【Linux】进程理解与学习…...

【三】一起算法---栈:STL stack、手写栈、单调栈
纸上得来终觉浅,绝知此事要躬行。大家好!我是霜淮子,欢迎订阅我的专栏《算法系列》。 学习经典算法和经典代码,建立算法思维;大量编码让代码成为我们大脑的一部分。 ⭐️已更系列 1、基础数据结构 1.1、链表➡传送门 1…...

电路设计的一些概念
锁存器的产生 论述1 (转)时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。 组合逻辑,由于数据要保持不变,只能通过锁存器来保存。 第一个代码,由于是时序逻…...

【Linux】Linux下权限的理解
前言:在之前我们已经对基本的指令进行了深入的学习,接下来我将带领大家学习的是关于权限的相关问题。在之前,我们一直是使用的【root】用户,即为“超级用户”,通过对权限的学习之后,我们就会慢慢的切换到普…...

Prometheus监控实战系列十七:探针监控
目前对于应用程序的监控主要有两种方式,一种被称为白盒监控,它通过获取目标的内部信息指标,来监控目标的状态情况,我们前面介绍的主机监控、容器监控都属于此类监控。另一种则是“黑盒监控”,它指在程序外部通过探针的…...
题目:JPA的懒加载失效是什么情况?
题目:JPA的懒加载失效是什么情况?Q1:什么是JPA的懒加载?Q2:JPA的懒加载会在什么情况下失效?Q3:如何避免JPA的懒加载失效?前言:在使用JPA进行数据库操作时,懒加…...
十六、消息推送
一、什么是消息推送? 消息推送通常是指网站的运营工作等人员,通过某种工具对用户当前网页或移动设备 APP 进行的主动消息推送。 消息推送一般又分为 Web 端消息推送和移动端消息推送。 消息推送无非是推(push)和拉(p…...

PMP项目管理-【第一章】引论
项目知识体系: 项目管理知识体系: 1.1 项目特性 独特性:独特性会带来不确定性(风险) 临时性:1> 任何项目都有起始终止时间 2> 项目具备临时性,项目成果可能是永久的 1.2 项目驱动变革 从商业角度来看,…...

前端布局小案例,分享3个漂亮的卡片组件
当今互联网发展迅猛,各种应用、网站和软件层出不穷,其中前端技术的发展更是让人瞩目。随着用户对于界面设计的要求越来越高,漂亮的卡片组件在各类网页设计中变得越来越流行。本文将分享三个精美的卡片组件,帮助您在前端开发中轻松…...
博客重载记录
博客重载记录流控算法实现open系统调用流程二分查找前言: 有时候看了一些比较好的文章,过几天就忘了,想想不如自己实现一遍博客代码或按博客结构自己写一遍,加深印象,但把别人的内容改个名字变成自己的博客,…...
open-cv绘制简单形状line() circle() rectangle() polylines() putText() cvtColor()
OpenCV彩色图像中一个像素是按照“B-G-R”模式组织的。 绘图函数的一些公众参数: img :图像对象 color: 颜色,如果彩色用一个三元组表示,三元组的元素按照B-G-R组织,三元组(0,255,0)中B为0,G为2…...

基于 PyTorch + LSTM 进行时间序列预测(附完整源码)
时间序列数据,顾名思义是一种随时间变化的数据类型。 例如,24小时内的温度、一个月内各种产品的价格、某家公司一年内的股票价格等。深度学习模型如长短期记忆网络(LSTM)能够捕捉时间序列数据中的模式,因此可以用于预…...

GEE页面介绍
目录一、背景二、用户界面三、数据类型:栅格1、请求图像集合2、学习查看栅格元数据3、矢量实例一:四、数据集五、数据属性1、空间分辨率2、时间分辨率六可视化多个波段1、真彩色(TCI)2彩色红外(CI)3、伪色 1 和 2 (FC1/FC2)七、可…...

python自动发送邮件,qq邮箱、网易邮箱自动发送和回复
在python中,我们可以用程序来实现向别人的邮箱自动发送一封邮件,甚至可以定时,如每天8点钟准时给某人发送一封邮件。今天,我们就来学习一下,如何向qq邮箱,网易邮箱等发送邮件。 一、获取邮箱的SMTP授权码。…...
hastcat
hashcat 下载地址: https://hashcat.net/hashcat/ 案例 Usage: hashcat [options]... hash|hashfile|hccapxfile [dictionary|mask|directory]...https://xz.aliyun.com/t/4008破解linux shadow /etc/shadow中密码格式: $id$salt$encrypted如:$1$2eWq10AC$NaQqalCk3 1表…...
242. 一个简单的整数问题
Powered by:NEFU AB-IN Link 文章目录242. 一个简单的整数问题题意思路代码242. 一个简单的整数问题 题意 给定长度为 N的数列 A,然后输入 M行操作指令。 第一类指令形如 C l r d,表示把数列中第 l∼r个数都加 d 第二类指令形如 Q x,表示询问…...

docker安装Redis高可用(一主二从三哨兵)
本次教程使用docker swarm安装 准备三台机器 hostIP用途node1192.168.31.130redis-master01,redis哨兵节点01node2192.168.31.131redis-slave01, redis哨兵节点02node3192.168.31.132redis-slave02 redis哨兵节点02 注意事项: 1:需要保证三…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...