socket的send(),recv()以及缓冲区之间的关系

来自:
socket编程缓冲区大小对send()的影响_wangst4321的专栏-CSDN博客
TCP/UDP的接收缓冲区和发送缓冲区_Swallow_he的博客-CSDN博客
socket之send与发送缓冲区大小的关系_水果刀的专栏-CSDN博客

每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的流量/拥塞控制便是依赖于这两个独立的缓冲区以及缓冲区的填充状态。

接收缓冲区

接收缓冲区把数据缓存到内核,应用进程一直没有调用recv()进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。不管进程是否调用recv()读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。

recv():把内核缓冲区中的数据拷贝到应用层用户的buffer里面,并返回。

发送缓冲区

进程调用send()发送的数据的时候,最简单情况(也是一般情况),将数据拷贝进入socket的内核(拷贝到内核就返回)发送缓冲区之中,然后send便会返回。recv()换句话说,send()返回之时,数据不一定会发送到对端去(和write写文件有点类似),只是完成了拷贝动作而已。

recv()send():仅仅是把应用层缓冲区的数据拷贝进socket的内核发送缓冲区中(send()只负责拷贝,拷贝到内核就返回),发送是TCP的事情,和send()其实没有太大关系。

数据发送和接收的过程:
在这里插入图片描述

tcp、udp接收缓冲区的不同

接收缓冲区被TCP和UDP用来缓存网络上来的数据,一直保存到上层应用进程读走为止。

对于TCP

如果应用进程一直没有读取,接收缓冲区满了之后,发生的动作是:接收端通知发送端,接收窗口关闭(win=0),这便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。

recv()如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。

查看测试机的socket发送缓冲区大小:

cat /proc/sys/net/ipv4/tcp_wmem

在这里插入图片描述
第一个值是一个限制值,socket发送缓存区的最少字节数;
第二个值是默认值;
第三个值是一个限制值,socket发送缓存区的最大字节数;

根据实际测试,发送缓冲区的尺寸在默认情况下的全局设置是16384字节,即16k。

对于udp

recv()每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发(尽最大能力交付),不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。

当套接口接收缓冲区满时,新来的数据报无法进入接收缓冲区,此数据报就被丢弃。UDP是没有流量控制的;快的发送者可以很容易地就淹没慢的接收者,导致接收方的UDP丢弃数据报。

缓冲区大小对send()的影响

Socket编程中,使用send()传送数据时,返回结果受到以下几个因素的影响:

  • Blocking模式或non-blocking模式
  • 发送缓冲区的大小
  • 接收窗口大小

send函数在发送的数据长度大于发送缓冲区大小,或者大于发送缓冲区剩余大小时,socket会怎么反应

socket之send与发送缓冲区大小的关系_水果刀的专栏-CSDN博客

recv()当send的数据长度大于socket的缓冲区长度时,不管是windows还是linux,阻塞还是非阻塞,send都会分帧发送,分帧到缓冲区能够接收的大小

猜你喜欢

转载自blog.csdn.net/qq_32523711/article/details/108986983