使用send()函数发送数据,系统如何知道数据发送成功

函数作用

我们知道,服务端中有一个接收缓存区,客户端中有一个发送缓存区,同时每个TCP socket在内核中也都有一个发送缓冲区和一个接收缓冲区,

 

send()函数的作用就是将客户端或服务端中的数据拷贝到SOCKET的发送缓存区中

 

recv()函数的作用就是将SOCKET的接收缓存区中数据拷贝到客户端或服务端的接收缓存区中

 

综上,send()函数和recv()函数只完成应用层到传输层的数据搬运,并不直接将数据传送到数据的另一端去,真正完成数据的传输的是协议功能(TCP/UDP)

 

函数参数

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

 

sockfd:创建的sockfd文件描述符,

buf:发送数据所在的数据区,

len:发送数据的长度,

flags:标志位默认设置为0

 

send()函数的返回值

 

1、成功执行时,返回发送的字节数。

 

2、失败则返回SOCKET_ERROR

 

 

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

 

recv()函数的返回值

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

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

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

 

如何判断数据是否发送成功?

通过send()函数的返回值,应用层只知道数据是否“拷贝”成功,另一端是否接收数据成功仅靠send()函数的返回值是判断不了的,

 

对方是否接收数据成功发送端是判断不了的,如果发送端需要知道接收端是否接收数据成功,需要接收端给发送端返回一个值来确定(应用层面确定数据发送成功)

 

系统底层确定数据是否发送成功(协议层面确定数据发送成功)

 

TCP协议会确保数据完整的发送出去,同时保证数据到达接收端的SOCKET接收缓存区

 

TCP数据报首部包含发送数据包的基本信息,比如数据长度

 

TCP协议的ACK确认机制

 

当SOCKET发送缓存区的大小为0的时候,也可以确定数据完全发送出去,buffer.size()==0

 

补充:

1、滑动窗口在SOCKET的缓存区里面,窗口的大小会根据接收端的处理情况动态变化(保证SOCKET的接收缓冲区不会溢出)

 

2、TCP 的SOCKET有接收缓存区和发送缓存区,而UDP的socket只有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。

 

posted @ 2020-03-26 10:51  知道了呀~  阅读(5001)  评论(0编辑  收藏  举报