socket中send和recv函数
Socket一次Recv接受的字节有限制么?

从套接字接收数据。 返回值是表示接收数据的字符串。 一次接收的最大数据量由bufsize指定。它默认为零。
注意为了最好地匹配硬件和网络现实,bufsize的值应该是2的相对较小的幂,例如4096。
经实际测试recv不同端口接收情况不同,当前我们默认为1024字节
大多数情况下为1448字节
TCP socket的buffer
每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式以及TCP的流量(拥塞)控制便是依赖于这两个独立的buffer以及buffer的填充状态。接收缓冲区把数据缓存入内核,应用进程一直没有调用recv()进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。再啰嗦一点,不管进程是否调用recv()读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。recv()所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面,并返回,仅此而已。进程调用send()发送的数据的时候,最简单情况(也是一般情况),将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。换句话说,send()返回之时,数据不一定会发送到对端去(和write写文件有点类似),send()仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中,发送是TCP的事情,和send其实没有太大关系。接收缓冲区被TCP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,接收缓冲区满了之后,发生的动作是:收端通知发端,接收窗口关闭(win=0)。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。因为对方不允许发出超过所通告窗口大小的数据。 这就是TCP的流量控制,如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。
send函数工作原理:
send函数只负责将数据提交给协议层。 当调用该函数时,send先比较待发送数据的长度len和套接字s的发送缓冲区的长度,如果len大于s的发送缓冲区的长度,该函数返回SOCKET_ERROR; 如果len小于或者等于s的发送缓冲区的长度,那么send先检查协议是否正在发送s的发送缓冲中的数据; 如果是就等待协议把数据发送完,如果协议还没有开始发送s的发送缓冲中的数据或者s的发送缓冲中没有数据,那么send就比较s的发送缓冲区的剩余空间和len; 如果len大于剩余空间大小,send就一直等待协议把s的发送缓冲中的数据发送完,如果len小于剩余空间大小,send就仅仅把buf中的数据copy到剩余空间里(注意并不是send把s的发送缓冲中的数据传到连接的另一端的,而是协议传的,send仅仅是把buf中的数据copy到s的发送缓冲区的剩余空间里)。 如果send函数copy数据成功,就返回实际copy的字节数,如果send在copy数据时出现错误,那么send就返回SOCKET_ERROR; 如果send在等待协议传送数据时网络断开的话,那么send函数也返回SOCKET_ERROR。
要注意send函数把buf中的数据成功copy到s的发送缓冲的剩余空间里后它就返回了,但是此时这些数据并不一定马上被传到连接的另一端。 如果协议在后续的传送过程中出现网络错误的话,那么下一个Socket函数就会返回SOCKET_ERROR。(每一个除send外的Socket函数在执行的最开始总要先等待套接字的发送缓冲中的数据被协议传送完毕才能继续,如果在等待时出现网络错误,那么该Socket函数就返回SOCKET_ERROR)
recv函数工作原理:
源码解释:
接收来自socket缓冲区对字节数据,当缓冲区没有数据可取时,recv会一直处于阻塞状态,直到缓冲区至少又一个字节数据可取,或者远程端关闭,关闭远程端并读取所有数据后,返回空字符串.
recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0 。
对方优雅的关闭socket并不影响本地recv的正常接收数据;如果协议缓冲区内没有数据,recv返回0,指示对方关闭;如果协议缓冲区有数据,则返回对应数据(可能需要多次recv),在最后一次recv时,返回0,指示对方关闭。
要点:
在进行TCP协议传输的时候,要注意数据流传输的特点,recv和send不一定是一一对应的(一般情况下是一一对应),也就是说并不是send一次,就一定recv一次就接收完,有可能send一次,recv多次才接收完,也可能send多次,一次recv就接收完了。TCP协议会保证数据的有序完整的传输,但是如何去正确完整的处理每一条信息,是程序员的事情。
例如:服务器在循环recv,recv的缓冲区大小为100byte,客户端在循环send,每次send 6byte数据,则recv每次收到的数据可能为6byte,12byte,18byte,这是随机的,编程的时候注意正确的处理。
socket中send和recv函数的更多相关文章
- SOCKET中send和recv函数工作原理与注意点
https://blog.csdn.net/rankun1/article/details/50488989
- linux内核中send与recv函数详解
Linux send与recv函数详解 1.简介 #include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t n ...
- socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题
Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...
- linux Socket send与recv函数详解
转自:http://www.cnblogs.com/blankqdb/archive/2012/08/30/2663859.html linux send与recv函数详解 1 #include ...
- [转]socket使用TCP协议时,send、recv函数解析以及TCP连接关闭的问题
Tcp协议本身是可靠的,并不等于应用程序用tcp发送数据就一定是可靠的.不管是否阻塞,send发送的大小,并不代表对端recv到多少的数据. 在阻塞模式下, send函数的过程是将应用程序请求发送的数 ...
- 分片传输——send和recv函数
最近在写socket编程收发数据,对于如何发送和接收大量数据,一直在思考.send和recv一般缓存区大小为4K,但是如果你要传输的数据超过了这个标准该如何做呢. 我想到的就是如改写write和rea ...
- socket函数send和recv函数
转自:http://www.cppblog.com/aaxron/archive/2012/04/27/172891.html 在发送端,一次发送4092个字节,在接收端,一次接收4092个字节,但是 ...
- send()和recv()函数详解
send()函数 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不论是客户还是服务器应用程序都用send函数来向TCP连 ...
- UNIX网络编程——send与recv函数详解
#include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags); ssize_ ...
随机推荐
- 最全的Spring注解详解
@Configuration : 配置类 == 配置文件,告诉Spring这是一个配置类@ComponentScan(value="com.atguigu",excludeFilt ...
- IO流----转换流、缓冲流
打开一个文本文件,另存为: Ansi就是系统默认编码(就是gbk) 建一个编码是utf-8的txt文件, 例: import java.io.FileWriter; import java.io.IO ...
- linux安装源文件(.tar.gz)
安装此类文件,分为7步: 1.首先把依赖的软件给装上,如果依赖perl,先装perl,如果依赖Pathon,现装pathon 2.tar 源软件路径 -C 新软件路径(注意这里一定要-C,不然不能解压 ...
- C#调用C++接口返回字符串的做法
作者:朱金灿 来源:http://blog.csdn.net/clever101 现在有这样一种情景,假如C#调用C++接口需要返回一个字符串.因为字符串是不定长的,因此传递一个定长的字符串进去是不合 ...
- 从零开始的Lua宅[1]:编译Lua解释器
Lua是一门神奇的脚本语言,游戏宅必备,懒人必备.Lua差多不是学起来用起来最简单的语言了,以至于简单到自身就是文档,自身就是配置文件.但是Lua的运行效率却是众多脚本中非常高的,据说仅次于V8爹下的 ...
- Yii2.0 集成使用富头像上传编辑器
在开发过程中,我们会用到头像上传的功能.这里给大家推荐一款比较流行的头像上传组件,FullAvatarEditor 2.3(富头像上传编辑器). 实际效果如图所示: 1.下载组件,下载地址:http: ...
- Windows Azure 配置Active Directory 主机(4)
步骤 6:设置在启动时加入域的虚拟机 若要创建其他在首次启动时加入域的虚拟机,请打开 Windows Azure PowerShell ISE,粘贴以下脚本,将占位符替换为您自己的值并运行该脚本. 若 ...
- C#实现灰度图像和彩色图像的4种镜像
一:灰度图像的水平镜像核心代码: 二:灰度图像的竖直镜像 核心代码:三:彩色图像的水平镜像 核心代码: 四:彩色图像的竖直镜像 核心代码:
- codeforce Gym 100685E Epic Fail of a Genie(MaximumProduction 贪心)
题意:给出一堆元素,求一个子集,使子集的乘积最大,如有多个,应该使子集元素个数尽量小. 题解:贪心,如果有大于1的正数,那么是一定要选的,注意负数也可能凑出大于1的正数,那么将绝对值大于1的负数两两配 ...
- CPP-基础:new int[]跟int()的区别
1. new int[] 是创建一个int型数组,数组大小是在[]中指定,例如: int * p = new int[10]; //p执行一个长度为10的int数组.2. new int()是创建一个 ...