send函数

不论是客户端还是服务器端应用程序都用send函数来向TCP连接的另一端发送数据。客户端程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。

当调用send函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区,如果len大于发送缓冲区的长度,该函数返回错误SOCKET_ERROR;如果len <= s的发送缓冲区,那么send先检查协议是否正在发送s的发送缓冲区中的数据,如果是就等待协议把数据发送完毕,如果协议还没有开始发送s的发送缓冲区中的数据或者s的发送缓冲区中没有数据,那么send就比较s的发送缓冲区的剩余空间和len,如果len > 剩余空间 send就一直等待协议把s的发送缓冲区中的数据发送完,如果len < 剩余空间 send就仅仅把buf中的数据copy到剩余空间里(send仅仅是把buf中的数据copy到s的发送缓冲区中,至于把数据传送到另一端是协议传的不是send)。如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误或者在等待协议传送数据时网络断开,那么send函数也返回SOCKET_ERROR。

要注意send函数把buf中的数据成功copy到s的发送缓冲区的剩余空间里,send函数就返回了,但是此时这些数据并不一定马上被传送到连接的另一端。如果协议在后续的传送过程中出现网络错误的话,那么下一个socket函数就会返回SOCKET_ERROR。但是注意的是:每一个除send以外的socket函数在执行的最开始总要等待套接字的发送缓冲区中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该socket函数就返回SOCKET_ERROR。

注意:在Unix系统之下,如果send在等待协议传送数据时网络断开,调用send的进程会接受到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

错误代码:

EBADF 参数s 非合法的socket处理代码。
EFAULT 参数中有一指针指向无法存取的内存空间
ENOTSOCK 参数s为一文件描述词,非socket。
EINTR 被信号所中断。
EAGAIN 此操作会令进程阻断,但参数s的socket为不可阻断。
ENOBUFS 系统的缓冲内存不足
ENOMEM 核心内存不足
EINVAL 传给系统调用的参数不正确。

recv函数

当调用recv函数时,recv函数先等待s的发送缓冲区中的数据都被协议传送完毕,如果协议在传送数据时出现了网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲区中没有数据或者协议成功发送完毕后,recv函数先检查s的接受缓冲区,如果s接收缓冲区中没有数据或者正在接收数据,那么recv函数久一直等待直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲区中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲区中的数据copy完毕。recv函数仅仅是拷贝数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv函数在copy时出错,返回SOCKET_ERROR,如果recv函数在等待协议接收数据时网络中断了,那么recv函数返回0。

注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

返回值说明

阻塞模式下recv会一直阻塞直到接收到数据,非阻塞模式下如果没有数据就会返回,不会阻塞着读,因此需要循环读取)。

返回说明:

(1)成功执行时,返回接收到的字节数。

(2)若另一端已关闭连接则返回0,这种关闭是对方主动且正常的关闭

(3)失败返回-1,errno被设为以下的某个值

特别地:返回值<0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的,继续接收。

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

EBADF:sock不是有效的描述词

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

EFAULT:内存空间访问出错

EINTR:操作被信号中断

EINVAL:参数无效

ENOMEM:内存不足

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

ENOTSOCK:sock索引的不是套接字

socket缓冲区

默认情况下socket是阻塞的。

send函数并不是直接将数据传输到网络中,而是负责将数据写入输出缓冲区,数据从输出缓冲区发送到目标主机是由TCP协议完成的。数据写入到输出缓冲区之后,send函数就可以返回了,数据是否发送出去,是否发送成功,何时到达目标主机,都不由它负责了,而是由协议负责。

recv函数也是一样的,它并不是直接从网络中获取数据,而是从输入缓冲区中读取数据。

输入输出缓冲区,系统会为每个socket都单独分配,并且是在socket创建的时候自动生成的。一般来说,默认的输入输出缓冲区大小为8K。套接字关闭的时候,输出缓冲区的数据不会丢失,会由协议发送到另一方;而输入缓冲区的数据则会丢失。

Socket数据发送与接收问题

数据的发送和接收是独立的,并不是发送方执行一次send,接收方就执行以此recv。recv函数不管发送几次,都会从输入缓冲区尽可能多的获取数据。如果发送方发送了多次信息,接收方没来得及进行recv,则数据堆积在输入缓冲区中,取数据的时候会都取出来。换句话说,recv并不能判断数据包的结束位置。

send函数:
在数据进行发送的时候,需要先检查输出缓冲区的可用空间大小,如果可用空间大小小于要发送的数据长度,则send会被阻塞,直到缓冲区中的数据被发送到目标主机,有了足够的空间之后,send函数才会将数据写入输出缓冲区。

TCP协议正在将数据发送到网络上的时候,输出缓冲区会被锁定(生产者消费者问题),不允许写入,send函数会被阻塞,直到数据发送完,输出缓冲区解锁,此时send才能将数据写入到输出缓冲区

要写入的数据大于输出缓冲区的最大长度的时候,要分多次写入,直到所有数据都被写到缓冲区之后,send函数才会返回。

recv函数:
函数先检查输入缓冲区,如果输入缓冲区中有数据,读取出缓冲区中的数据,否则的话,recv函数会被阻塞,等待网络上传来数据。如果读取的数据长度小于输出缓冲区中的数据长度,没法一次性将所有数据读出来,需要多次执行recv函数,才能将数据读取完毕。

参考:

https://blog.csdn.net/u010270148/article/details/53605339

https://www.cnblogs.com/sunziying/p/6501045.html

https://www.cnblogs.com/Berryxiong/p/6547510.html

https://www.cnblogs.com/msb-/articles/6042413.html

https://blog.csdn.net/u010871058/article/details/76147082

send/recv与socket相关推荐

  1. socket c语言 AF_TIPC,socket编程 send() recv() sendto() recvfrom()

    socket编程 send() recv() sendto() recvfrom() int socket( int af, int type, int protocol); af: 指定一个协议簇( ...

  2. easyHOOK socket send recv

    代码比较简单,就不做注释了.  包含一个sockethookinject.DLL 和sockethook.exe 有一点不清楚, SetExclusiveACL可以添加当前线程的hook, 但是eas ...

  3. send(),recv()函数详解

    1.send 函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP ...

  4. php socket recv 超时,socket编程中的超时设置示例详解之一

    简介: 在网络通讯中,如果socket处于阻塞模式运行时,就需要考虑处理socket操作超时的问题. 所谓阻塞模式,是指其完成指定的操作之前阻塞当前的进程或线程,直到操作有结果返回. 在我们直接调用s ...

  5. RDMA send/recv 和 read/write操作

    RDMA one-side 和 two-side原语 在RDMA传输中,SEND/RECEIVE是双边操作,即需要通信双方的参与,并且RECEIVE要先于SEND执行,这样对方才能发送数据,当然如果对 ...

  6. Socket api接口--Send(),Recv()的长度问题

    一个包没有固定长度,以太网限制在46-1500字节,1500就是以太网的MTU,超过这个量,TCP会为IP数据报设置偏移量进行分片传输,现在一般可允许应用层设置8k(NTFS系统)的缓冲区,8k的数据 ...

  7. linux设置send时间,[转]Socket 的send,recv在windows与linux下的超时设置

    从昨天到今天一真在搞这个网络断线检测的问题,一直没搞好,网上大多都说用ping 可以搞定,不过我就是搞不定,没办法之下想了个不是办法的办法,在 服务器上开了一个 UDP端口,监听数据,然后回发,不用T ...

  8. linux socket中 send recv函数的 flags参数

    int send(int s, const void *msg, size_t len, int flags);  flags取值有: 0: 与write()无异 MSG_DONTROUTE:告诉内核 ...

  9. send/recv阻塞和非租塞不同

    [send]在阻塞模式下, send函数的过程是将应用程序请求发送的数据拷贝到发送缓存中发送就返回.但由于发送缓存的存在,表现为:如果发送缓存大小比请求发送的大小要大,那么send函数立即返回,同时向 ...

  10. python send 案例_python socket编程入门(编写server实例)+send 与sendall的区别与使用方法...

    python 编写server的步骤: 1. 第一步是创建socket对象.调用socket构造函数.如: socket = socket.socket( family, type ) family参 ...

最新文章

  1. Python之Fabric
  2. Html与Css关联到一起
  3. 报错: eclipse加载maven工程提示pom.xml无法解析org.apache.maven.plugins:maven-resources-plugin:2.3.2...
  4. JDBC oracle 错误总结
  5. 性能监控工具 NewRelic 简介
  6. A new image format for the Web
  7. CentOs7下lnmp环境安装
  8. Normalization
  9. StringBuilder与StringBuffer比较
  10. [ZJOI2010] 基站选址(线段树优化dp)
  11. 修改MYSQL 密码
  12. Android 手机卫士--解析json与消息机制发送不同类型消息
  13. JavaScript Tip之:用和||来模拟if-else
  14. flutter弹框怎么封装_Flutter初始化时 弹出弹出框
  15. 计算机仿真matlab编程,MATLAB与计算机仿真
  16. python库手册_Python 中文开发手册
  17. 匹配区县代码_省份、城市、区县三级联动Html代码
  18. 静心的全部秘密:你是观照者
  19. Win10系统安装office后excel等文件图标显示异常
  20. Java爬堆糖图片爬虫

热门文章

  1. 全国软考中级软件设计师 学习笔记-数据结构及算法部分
  2. Web Server 配置及上传文件
  3. 汇编语言--DOSBox 0.74的安装与简单使用
  4. LSTM神经网络实战
  5. HTML实现在线取色器
  6. php gmssl,关于GmSSL
  7. mysql数据库多表查询出来多条重复数据--处理方法--distinct
  8. SQL笔试经典50题
  9. Python(PyCharm)的下载安装汉化(2022)
  10. Powertoys windows 10第三方桌面分块(分区)工具