Linux socket里的send和recv,阻塞与非阻塞socket、TCP与UDP的区别

273 篇文章 12 订阅
订阅专栏
本文详细解析了socket编程中的send和recv函数,包括参数、返回值和工作原理。send函数将数据拷贝到发送缓冲区,根据缓冲区空间和状态决定是否阻塞;recv函数则从接收缓冲区拷贝数据到用户空间,同样处理阻塞和非阻塞情况。文章还对比了TCP与UDP在缓冲区使用上的差异,并阐述了阻塞与非阻塞在发送和接收时的不同行为。最后,讨论了TCP的流量控制机制。
摘要由CSDN通过智能技术生成

1. send函数

#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数:sockfd是socket()的返回值,文件描述符;buf是待发送数据所在的数据区的指针;len是发送数据的长度;flags标志位,默认为0。

返回值:(阻塞与非阻塞没有区别)>0表示成功将数据复制到缓冲区中,返回的值表示发送的字节数;=0表示对方主动关闭了连接过程;<0表示出错,会返回SOCKET_ERROR。

send发送数据实际上是将数据(应用层buf中的数据)拷贝到套接字sockfd的缓冲区(内核中的sockfd对应的发送缓冲区)中,内核中的发送缓存中的数据由协议(TCP,UDP没有发送缓冲区)传输。send函数将buf中的数据成功拷贝到发送缓冲区后就返回了,如果协议后续发送数据到接收端出现网络错误的话,那么下一个socket函数就会返回SOCKET_ERROR。

send发送数据时,首先比较待发送的数据长度len和套接字sockfd的发送缓冲区的长度,

  (1)如果待发送数据的长度len大于sockfd发送缓冲区的长度,则返回SOCKET_ERROR;

  (2)如果待发送数据的长度len小于等于sockfd发送缓冲区的长度,则再检查协议是否正在发送sockfd的发送缓冲区的数据, 

      【1】如果正在发送,则等协议把发送缓冲区中的数据发送完毕后(这里应该有阻塞和非阻塞的区别,阻塞的话等待数据的发送完毕,非阻塞的话立即返回,并将errno置为EAGAIN),将待发送的数据拷贝到sockfd的发送缓冲区中;

      【2】如果没有在发送数据,或发送缓冲区中没有数据,则比较sockfd的发送缓冲区的剩余空间和待发送数据的长度len:

        A. 如果剩余空间大于待发送数据的长度len,则将buf里的数据拷贝到剩余空间里;

        B. 如果剩余空间小于待发送数据的长度len,则等待协议把sockfd的发送缓冲区中的数据发送腾出空间(收到接收方的确认)(阻塞与非阻塞的区别,见ps的1),再将待发送数据拷贝到发送缓冲区中。

PS:1. 如果剩余空间小于待发送数据的长度len,阻塞socket会等待协议将发送缓冲区中的数据发送(缓冲区应该要收到接收方的确认之后,才能腾出空间),再拷贝待发送的数据并返回;非阻塞socket会尽力拷贝(能拷多少拷多少),返回已拷贝字节的大小,如果缓冲区可用空间为0,则返回-1,并置errno为EAGAIN((不确定)。

2. TCP有发送缓冲区,数据发送是协议发送发送缓冲区的内容;UDP没有发送缓冲区,UDP有数据要发送时,直接发送到网络上,不会缓存。

3. 接收端的sockfd缓冲区(内核的缓冲区)收到数据包后,就会返回ACK,不会等待recv到用户空间再返回。

2. recv函数

#include <sys/types.h>

 #include <sys/socket.h>

 ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数:sockfd是socket()的返回值,文件描述符;buf是接受数据的缓存区的指针;len是发送数据的长度;flags标志位,默认为0。

返回值:(阻塞与非阻塞没有区别)>0表示成功,此时的值是接收到的数据大小;=0表示对方调用了close API来关闭连接;<0表示出错,<0且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收,此时,errno被设为下面的某个值:

  EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时,连接正常,继续接收

  EBADF:sock不是有效的描述词

  ECONNREFUSE:远程主机阻绝网络连接

  EFAULT:内存空间访问出错

  EINTR:操作被信号中断,连接正常,继续接收

  EINVAL:参数无效

  ENOMEM:内存不足

  ENOTCONN:与面向连接关联的套接字尚未被连接上

  ENOTSOCK:sock索引的不是套接字

recv仅仅将接收到的数据(存储在内核的接受缓冲区)拷贝到buf(应用层用户的缓存区)中,真正的接受数据是由协议(TCP/UDP,UDP调用的函数名称不同)完成的。

recv先检查sockfd的发送缓冲区中有没有数据:

  (1)如果发送缓冲区中有数据,先等待sockfd的发送缓冲区的数据被协议发送完毕;如果协议在传送发送缓冲区的数据时出现网络错误,则返回SOCKET_ERROR;

  (2)如果sockfd发送缓冲区中的数据发送完毕或者发送缓冲区中没有数据,则检查sockfd的接收缓冲区,如果接受缓冲区中没有数据或者协议正在接收数据,那么recv一直等待(阻塞socket将等待,非阻塞socket直接返回-1,errno置为EWOULDBLOCK),直到协议将数据接受完毕;当协议把数据接收完毕,recv函数就把sockfd的接受缓冲区中的数据拷贝到buf中,然后返回拷贝的字节数。(注:协议接收到的数据的长度可能大于buf的长度,此时要调用几次recv函数才能把sockfd接受缓冲区中的数据拷贝完。)

 3. 阻塞与非阻塞的区别

发送时:在发送缓冲区的空间大于待发送数据的长度的条件下,阻塞socket一直等到有足够的空间放待发送的数据,将数据拷贝到发送缓冲区中才返回;非阻塞socket在没有足够空间时,会拷贝部分,并返回已拷贝的字节数,置errno为EWOULDBLOCK(不确定置为啥)。

接收时:如果sockfd发送缓冲区中有数据,或接受缓冲区中无数据,或协议正在接受数据,阻塞socket都将等待,直到有数据可以拷贝到用户程序中;非阻塞socket会返回-1,置errno为EWOULDBLOCK,表示“没有数据,回头来看”。

4. TCP与UDP的区别,TCO如何使用缓冲区实现流量控制

TCP有发送缓冲区和接收缓冲区;UDP只有接受缓冲区,UDP发送时不缓存,直接发送出去。对于接收缓冲区,TCP和UDP的recv操作相同,分为阻塞与非阻塞socket。

TCP的sockfd的接收缓冲区如果满了之后,接收端通知发送端,接收窗口关闭(win=0),保证了TCP套接口接收缓冲区不溢出,从而实现可靠传输;如果发送方无视窗口大小,仍然发送,则接收方TCP丢失收到的包。这就是TCP的流量控制(流量控制是点对点的)

UDP的接受缓冲区满了之后,对方并不知道,新来的数据报无法进入缓冲区,直接被丢弃,所以UDP没有流量控制,快的发送者可以将慢的接收方淹没,导致接收方丢弃数据包。

5. send和recv图示

linux C语言socket函数send
数字人生
01-20 2416
Linux中,使用C语言进行网络编程时,send函数是用于发送数据到已连接的套接字的重要函数之一。它通常用于TCP连接,但也可以用于UDP(尽管对于UDP,通常更推荐使用sendto,因为它允许你指定目标地址和端口)。下面是send
linuxsendrecv
weixin_33719619的博客
06-19 122
2019独角兽企业重金招聘Python工程师标准>>> ...
Linux系统编程(15)send/recv函数
最新发布
weixin_68239724的博客
08-23 1052
粘包问题是网络编程中常遇到的一个问题,尤其是在使用 TCP 协议的情况下。由于 TCP 是一种面向字节流的协议,它不会维护消息边界,可能会导致多个独立发送的数据包在接收方被粘连在一起。抓包是指通过特定工具捕获网络中传输的数据包,以便分析其内容、结构和传输状态。是在网络编程中常用的两个函数,用于在套接字(socket)之间发送和接收数据。:如果发送方频繁地发送小数据包,接收方可能会在缓冲区中接收到这些小包的组合。:成功时返回实际发送的字节数,失败时返回 -1。用于接收来自连接的套接字的数据。
linux socketsend()&recv()调用
weixin_30883311的博客
12-27 175
1.send 函数   int send( SOCKET s, const char FAR *buf, int len, int flags );   不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。   该函数的第一个参数指定发送端套接字描述符;   第二个参数指明...
LinuxSocket编程中用send发送结构体
weixin_34227447的博客
05-24 132
2019独角兽企业重金招聘Python工程师标准>>> ...
阻塞非阻塞区别
Rookie20190715的博客
08-26 664
简单点说: 阻塞就是干不完不准回来, 非阻塞就是你先干,我现看看有其他事没有,完了告诉我一声 我们拿最常用的sendrecv两个函数来说吧… 比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话…这时候...
python数据分析与可视化-02-socketsendrecv的原理剖析.ev4.rar
04-10
在本教程"python数据分析与可视化-02-socketsendrecv的原理剖析.ev4.rar"中,我们将深入探讨Python如何通过socket库进行网络通信,特别是`send`和`recv`这两个核心函数的使用与原理。 首先,让我们来理解什么是...
Socket-send-and-recv-.rar_c socket send recv_socket
09-21
Socket API提供了sendrecv函数,它们是TCP/IP通信的核心组件,用于在套接字之间发送和接收数据。在C语言环境中,socket编程主要涉及到以下知识点: 1. **套接字(Socket)概念**:套接字是网络通信的一种端点,...
linuxsend函数缓冲区问题,TCP Send函数的阻塞非阻塞,以及TCP发送数据的异常情况...
weixin_33838896的博客
05-03 1448
有了 TCP 协议本身的 ACK 机制为什么还需要业务层的ACK 机制?答:这个问题从操作系统(linux/windows/android/ios)实现TCP协议的原理角度来说明更合适:1 操作系统在TCP发送端创建了一个TCP发送缓冲区,在接收端创建了一个TCP接收缓冲区;2 在发送端应用层程序调用send()方法成功后,实际是将数据写入了TCP发送缓冲区;3 根据TCP协议的规定,在TCP连接...
c++非阻塞客户端/服务器TCP连接 socket编程代码示例
SleepyPikechu的博客
09-29 2100
话不多说 直接上代码 服务器 #ifndef __TCP_SERVER__ #define __TCP_SERVER__ #include "tcpServer.h" #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> #include &...
学习笔记(03):C++网络编程进阶-socket阻塞非阻塞
weixin_38793855的博客
03-01 1279
C/S模型在企业级的软件开发中非常常见,高并发网络通讯更是很多项目的核心模块,学好socket 网络编程显得尤为重要,本课程分为TCP/IP 协议、socket基础与进阶的异步通讯模型三个部分,通过浅显易懂的代码与讲解,让你的C++网络编程能力得到质的飞跃,具备开发高并发服务器的能力!...
Linux下的Socket编程实例(阻塞非阻塞)
06-05
Linux下基于C/C++的Socket阻塞和异步编程实例
Linux socket recv send
xiaohuangcat的专栏
01-15 1481
http://bbs.chinaunix.net/thread-2030722-1-1.html 如果服务端的程序关闭后,端口不能马上释放掉,需要等一会才能小时,在这之间再启动服务程序是起不来的,但是可以用这个函数,边面这种情况,服务程序关闭后,可以马上再起一次,不会冲突了。 setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(&
socket中的recv/send阻塞非阻塞区别
肖氏专栏
06-09 1504
==> recv/send参数中都会指定length  ==> 阻塞send:拷到发送缓冲区,如果缓冲区满,则需等待直到指定长度的数据发送到缓冲区  ==> 非阻塞send:一直拷贝,如果缓冲区满,也立即返回,并不等待。  ==> 阻塞recv:直到接到到指定长度的数据为止  ==> 非阻塞recv:立即返回,不管缓冲区是否有数据,或者数据是否够指定长度,都立即返回
recvsend 阻塞非阻塞区别
布袋和尚
02-25 1892
目录 答案 深入说明 在 epoll 中的应用 答案 阻塞,事情干不完就不要回来了! 非阻塞,能干多少就是多少,赶紧回来! 深入说明 // 将内核接收缓冲区中的数据 copy 到应用层中用户的 buffer 中。 int recv(int sockfd, void *buf, size_t len, int flag); // 将应用层中用户的 buffer 中的数据 copy...
linux C语言socket函数recv
数字人生
01-20 2621
recv函数是在 Linux C 语言网络编程中用于从已连接的套接字接收数据的函数。它通常与 TCP 连接一起使用,但也可以用于 UDP(尽管对于 UDP,更常使用recvfrom,因为它还可以接收发送方的地址信息)。
TCPsend & recv
高性能架构探索
08-16 3572
接触过网络开发的人,大抵都知道,上层应用使用send函数发送数据,使用recv来接收数据,而sendrecv的实现原理又是怎样的呢? 在前面的几篇文章中,我们有提过,TCP是个可靠的、全双工协议。其流量控制或者拥塞控制依赖于滑动窗口和拥塞窗口的滑动来实现,而这两个窗口的滑动实现则是依赖于TCP中的两个buffer,这两个buffer则是TCP socket在内核中的发送缓冲区(send buffer)和接收缓冲区(recv buffer)。 在本文中,我们首先会简单介绍下TCP中发送缓冲区和接收缓..
linux_socket网络套接字函数(TCP通信)-socket函数-bind函数-listen函数-accept函数-connect函数-send函数-recv函数
qq_44177918的博客
05-07 1704
socket函数 bind函数 listen函数 accept函数 connect函数 send函数 recv函数 首先将整个结构体清零,然后设置地址类型为AF_INET,网络地址为INADDR_ANY,这个宏表示本地的任意IP地址,因为服务器可能有多个网卡,每个网卡也可能绑定多个IP地址,这样设置可以在所有的IP地址上监听,直到与某个客户端建立了连接时才确定下来到底用哪个IP地址,端口号为6666。客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是
Linux Socket 网络编程 sendrecv 使用注意事项
Dablelv 的博客专栏。
09-25 9994
(2)如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据,如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len;(4)如果len小于剩余空间大小,send就仅仅把buf中的数据copy到剩余空间(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传送的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间)。
写文章

热门文章

  • git生成patch和打patch 107059
  • 使用gdb添加断点的几种方式 31338
  • 手机烧屏概述 17730
  • C++11中的default函数 16101
  • C++ 打印 vector 的几种方法 15524

分类专栏

  • 我的博客 273篇

最新评论

  • git生成patch和打patch

    tianyazhichiC: 为什么我使用 git diff > patch 和 git apply patch 生成补丁和打补丁操作没有成功?有成功的吗?

  • shell脚本变量比较

    CSDN-Ada助手: CS入门 技能树或许可以帮到你:https://edu.csdn.net/skill/gml?utm_source=AI_act_gml

  • 解决ChatGPT发送消息没有反应

    司徒爵洛: 试了 还是不行 该怎么办表情包

  • 加载和启动过程

    普通网友: 文章构思巧妙,结构紧凑,既有深度又有广度,读后让人受益匪浅,确实是一篇值得一读的佳作。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

  • Linux pthread

    普通网友: 支持一下,细节很到位!【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】

最新文章

  • CMake变量作用域
  • prebuilts
  • 钩子函数和回调函数
2024
10月 5篇
09月 15篇
08月 3篇
07月 7篇
06月 11篇
05月 10篇
04月 13篇
03月 9篇
02月 11篇
01月 7篇
2023年85篇
2022年36篇
2021年42篇
2020年26篇
2018年1篇
2017年1篇
2016年1篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家清远玻璃钢雕塑造型陕西多彩玻璃钢雕塑多少钱常见商场美陈费用湘潭玻璃钢商场美陈惠州玻璃钢雕塑规定沈阳玻璃钢花盆公司大型玻璃钢雕塑什么好张家界园林玻璃钢雕塑制作佛山玻璃钢人物雕塑批发报价梅州工艺玻璃钢卡通雕塑哪里能买到玻璃钢雕塑商场珠宝美陈东台玻璃钢雕塑商场美陈装饰效果图文山玻璃钢花盆广东通道商场美陈市场六安卡通玻璃钢雕塑西安园林雕塑玻璃钢漯河玻璃钢雕塑雕刻加工长安玻璃钢花盆花器东莞自发光动物玻璃钢雕塑南京室内玻璃钢雕塑加工厂家四川通道商场美陈多少钱杭州玻璃钢雕塑定做加工云南优质校园玻璃钢景观雕塑济宁动物玻璃钢雕塑公司正阳玻璃钢雕塑定制上海市美陈商场吉安玻璃钢卡通人物雕塑工厂太原 玻璃钢 雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化