转自:https://murphypei.github.io/blog/2019/08/socket-ready
https://blog.csdn.net/kyang_823/article/details/79496303
https://blog.csdn.net/tantion/article/details/86502529
数据的发送和接收是独立的,并不是发送方执行一次send,接收方就执行以此recv。recv函数不管发送几次,都会从输入缓冲区尽可能多的获取数据。如果发送方发送了多次信息,接收方没来得及进行recv,则数据堆积在输入缓冲区中,取数据的时候会都取出来。换句话说,recv并不能判断数据包的结束位置。
send函数:
在数据进行发送的时候,需要先检查输出缓冲区的可用空间大小,如果可用空间大小小于要发送的数据长度,则send会被阻塞,直到缓冲区中的数据被发送到目标主机(内核缓冲区对应数据删掉,有了空间后),有了足够的空间之后,send函数才会将数据写入输出缓冲区。
TCP协议正在将数据发送到网络上的时候,输出缓冲区会被锁定(生产者消费者问题),不允许写入,send函数会被阻塞,直到数据发送完,输出缓冲区解锁,此时send才能将数据写入到输出缓冲区。
要写入的数据大于输出缓冲区的最大长度的时候,要分多次写入,直到所有数据都被写到缓冲区之后,send函数才会返回。
recv函数:
函数先检查输入缓冲区,如果输入缓冲区中有数据,读取出缓冲区中的数据,否则的话,recv函数会被阻塞,等待网络上传来数据。如果读取的数据长度小于输出缓冲区中的数据长度,没法一次性将所有数据读出来,需要多次执行recv函数,才能将数据读取完毕。
引用《Unix网络编程》中的解释:
当满足下列条件之一时,一个套接字准备好读:
SO_RCVLOWAT
套接字选项设置该套接字的低水位标记。对于 TCP 和 UDP 套接字而言,其默认值为 1,这意味着,默认情况下,只要缓冲区中有数据,那就是可读的。errno
设置成确切的错误条件。这些待处理错误也可以通过指定 SO_ERROR
套接字选项调用 getsockopt
获取并清除。当满足下列条件之一时,一个套接字准备好写:
SO_SNDLOWAT
套接字选项来设置该套接字的低水位标记。对于 TCP 和 UDP 套接字而言,其默认值通常为 2048,送缓冲区默认大小为8K,这意味着,默认情况下,一个套接字连接成功后,总是可写的。(至少需要2k的空闲空间才能写,send才不会阻塞)【为什么不会阻塞?写操作调用send从用户缓冲区发送到内核缓冲区,这个复制的过程不会阻塞吗?难道不是小于等于的时候直接写入用户缓冲区,这个过程不会阻塞吗?关于这个问题,本人目前认为,send调用后只要有>2k的空间就可以返回写入的字节数,然后后续由用户复制到内核这个过程不需要阻塞,自动完成就好了。】SIGPIPE
信号。connect
的套接字已建立连接,或者已经以失败告终。errno
设置成确切的错误条件。这些待处理的错误也可以通过指定 SO_ERROR
套接字选项调用 getsockopt
获取并清除。//针对第一条有疑问,发送缓冲区是将数据send到内核缓冲区,那么这个过程为什么不会阻塞呢?有系统调用的吧?需要具体理解send socket的过程,
【目前的理解是,写操作不会阻塞,只是说明发送区有数据发送,而无需等待数据。】
【居然看错了,第一条说的是发送缓冲区中可用空间字节数,而不是已存字节数。这是为了保证应用程序输出的数据能写到发送缓冲区,然后send返回,之后再系统调用写到内核缓冲区吧,只要发送有空间,内核那边应该没问题,或者是有回调告诉内核还剩多少空间。】
https://blog.csdn.net/majianfei1023/article/details/45788591
通俗的解释一下,缓存区我们当成一个大小为 n bytes的空间,那么:
https://blog.csdn.net/kyang_823/article/details/79496303
接收低水位标记和发送低水位标记:允许应用进程控制在select返回可读、可写时有多少数据可读、有多大空间可用于写。
接收低水位标记:让select返回”可读”时套接字接收缓冲区中所需的最少数据量。对于TCP,其默认值为1。【只要有一个就可以处于读就绪】
发送低水位标记:让select返回”可写”时套接字发送缓冲区中所需的最少可用空间。对于TCP,其默认值常为2048。【只要有2048空闲就可以处于写就绪】
接收低水位标记例子:若应用进程需要至少64个字节,否则无法有效工作,那就可以将接收低水位标记设为64,以防select在低于64字节时仍然唤醒该进程。
原文:https://www.cnblogs.com/BlueBlueSea/p/14808177.html