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 传给系统调用的参数不正确
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/3611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是Java的垃圾回收机制?

参考答案 垃圾回收机制&#xff0c;简称 GC Java 语言不需要程序员直接控制内存回收&#xff0c;由 JVM 在后台自动回收不再使用的内存提高编程效率保护程序的完整性JVM 需要跟踪程序中有用的对象&#xff0c;确定哪些是无用的&#xff0c;影响性能特点 回收 JVM 堆内存里的…

算法:贪婪算法、分而治之

算法&#xff1a;贪婪算法、分而治之 文章目录1.贪婪算法计数硬币实例12.分而治之分割/歇征服/解决合并/合并实例23.动态规划对照实例34.基本概念算法数据定义数据对象内置数据类型派生数据类型基本操作1.贪婪算法 设计算法以实现给定问题的最佳解决方案。在贪婪算法方法中&am…

数学原理—嵌入矩阵

目录 1.嵌入矩阵的基本作用 2.嵌入矩阵的数学解释 3.嵌入矩阵在联合分布适应中的数学推导主要包括以下几个步骤 4.在JDA中&#xff0c;怎么得到嵌入矩阵 5.联合分布自适应中如何得到嵌入矩阵 &#xff08;另一种解释&#xff09; 1.嵌入矩阵的基本作用 在机器学习中&a…

【密码学复习】第四讲分组密码(三)

AES算法的整体结构 AES算法的轮函数 1&#xff09;字节代换&#xff08;SubByte&#xff09; 2&#xff09;行移位&#xff08;ShiftRow&#xff09; 3&#xff09;列混合&#xff08;MixColumn&#xff09; 4&#xff09;密钥加&#xff08;AddRoundKey&#xff09;1-字节代换…

【HTML系列】第一章 · HTML入门

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ &#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x…

SpringBoot系列 logback-spring日志配置使用记录以及解决依赖包冲突问题

SpringBoot推荐使用logback-spring.xml SpringBoot官方推荐使用logback-spring.xml作为logback框架的自定义日志配置文件&#xff08;例如&#xff1a;使用logback-spring.xml而不是logback.xml&#xff09;&#xff0c;因为带-spring后缀的配置文件可以使用SpringBoot提供的一…

python基础语法(下)

目录 0、前期回顾 1、python的输出 2、python的输入 3、运算符 ​编辑4、test 0、前期回顾 先说个问题 我用python的环境直接打开py文件会闪退 其实原因是这个文件正在被执行没关闭就直接发过来了 只需要用其它文本编辑器打开就行了 # 1. 注释 # 单行注释与多行注释 …

docker安装Redis高可用(一主二从三哨兵)

本次教程使用docker swarm安装 准备三台机器 hostIP用途node1192.168.31.130redis-master01&#xff0c;redis哨兵节点01node2192.168.31.131redis-slave01, redis哨兵节点02node3192.168.31.132redis-slave02 redis哨兵节点02 注意事项&#xff1a; 1&#xff1a;需要保证三…

MP4怎么转换成MP3格式?两种方法帮你实现

MP4是一种常见的视频格式&#xff0c;而MP3则是一种音频格式。有时候&#xff0c;我们需要将MP4视频转换为MP3音频&#xff0c;例如从YouTube下载视频后只需要提取其中的音频部分。以下是两种方法帮助您实现MP4到MP3的转换。 方法一&#xff1a;使用在线转换工具 在线转换工具…

搭建一个双系统个人服务器

搭建一个双系统个人服务器0.前言一、双系统安装1.磁盘划分2.windows安装3.ubuntu安装二、系统启动项美化&#xff1a;1. refind引导2. 美化 grub 界面三、系统代理0.前言 年后找了份工作&#xff0c;忙于适应新环境所以更新也减缓了&#xff0c;最近闲暇时间给个人电脑进行了整…

水果新鲜程度检测系统(UI界面+YOLOv5+训练数据集)

摘要&#xff1a;水果新鲜程度检测软件用于检测水果新鲜程度&#xff0c;利用深度学习技术识别腐败或损坏的水果&#xff0c;以辅助挑拣出新鲜水果&#xff0c;支持实时在线检测。本文详细介绍水果新鲜程度检测系统&#xff0c;在介绍算法原理的同时&#xff0c;给出Python的实…

dfs和bfs能解决的问题

一.理解暴力穷举之dfs和bfs暴力穷举暴力穷举是在解决问题中最常用的手段&#xff0c;而dfs和bfs算法则是这个手段的两个非常重要的工具。其实&#xff0c;最简单的穷举法是直接遍历&#xff0c;如数列求和&#xff0c;遍历一个数组即可求得所问答案&#xff0c;这与我在前两篇博…

给准备面试网络工程师岗位的应届生一些建议

你听完这个故事&#xff0c;应该会有所收获。最近有一个23届毕业的大学生和我聊天&#xff0c;他现在网络工程专业大四&#xff0c;因为今年6、7月份的时候毕业&#xff0c;所以现在面临找工作的问题。不管是现在找一份实习工作&#xff0c;还是毕业后找一份正式工作&#xff0…

QT表格控件实例(Table Widget 、Table View)

欢迎小伙伴的点评✨✨&#xff0c;相互学习&#x1f680;&#x1f680;&#x1f680; 博主&#x1f9d1;&#x1f9d1; 本着开源的精神交流Qt开发的经验、将持续更新续章&#xff0c;为社区贡献博主自身的开源精神&#x1f469;‍&#x1f680; 文章目录前言一、图示实例二、列…

Cookie 和 Session的区别

文章目录时间&#xff1a;2023年3月23日第一&#xff1a;什么是 Cookie 和 Session ?什么是 Cookie什么是 Session第二&#xff1a;Cookie 和 Session 有什么不同&#xff1f;第三&#xff1a;为什么需要 Cookie 和 Session&#xff0c;他们有什么关联&#xff1f;第四&#x…

Python接口自动化 ❀ 详解 Cookie-Session登录验证 的工作原理

Python接口自动化 ❀ 详解 Cookie-Session登录验证 的工作原理前言1、Cookie&Session❀ 为什么不能单独使用Cookie&#xff1f;❀ Session是如何与Cookie结合的&#xff1f;2、Cookie&Session的缺陷❀ 存储问题❀CSRF问题3、session和cookie的区别与联系前言 目前绝大…

机器学习:基于KNN对葡萄酒质量进行分类

机器学习&#xff1a;基于KNN对葡萄酒质量进行分类 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x1f44d;收藏…

【SpringAOP】AOP面向切面编程

目录 一、什么是AOP 二、为什么有AOP 三、AOP相关概念 四、SpringAOP代码案例 1、添加SpringAOP依赖 2、定义切面 3、定义切点 4、实现通知 一、什么是AOP AOP&#xff1a;AOP—Aspect Oriented Programming&#xff08;面向切面编程&#xff09;&#xff0c;是对OOP&…

微信小程序面试题(day08)

文章目录微信小程序自定义组件的使用&#xff1f;微信小程序事件通道的使用&#xff1f;微信小程序如何使用vant组件库&#xff1f;微信小程序自定义组件父传子子传父&#xff1f;微信小程序自定义组件生命周期有哪些&#xff1f;微信小程序授权登录流程&#xff1f;web-view。…
最新文章