当前位置:首页 > 公众号精选 > 小林coding
[导读]今天又是被倾盆的需求淹没的一天。有没有人知道,那种“我用3句话,就让产品为我砍了18个需求”的鸡汤课在哪报名,想报。"听懂掌声"的那种课就算了,太费手了。扯远了,回到我们今天的正题,我们了解下这篇文的目录。目录代码执行send成功后,数据就发出去了吗?回答这个问题之前,需要了解什...

今天又是被倾盆的需求淹没的一天。

有没有人知道,那种“我用3句话,就让产品为我砍了18个需求”的鸡汤课在哪报名,想报。

"听懂掌声"的那种课就算了,太费手了。

扯远了,回到我们今天的正题,我们了解下这篇文的目录。

目录
代码执行send成功后,数据就发出去了吗?

回答这个问题之前,需要了解什么是Socket 缓冲区


Socket 缓冲区

什么是 socket 缓冲区

编程的时候,如果要跟某个IP建立连接,我们需要调用操作系统提供的 socket API

socket 在操作系统层面,可以理解为一个文件

我们可以对这个文件进行一些方法操作

listen方法,可以让程序作为服务器监听其他客户端的连接。

connect,可以作为客户端连接服务器。

sendwrite可以发送数据,recvread可以接收数据。

在建立好连接之后,这个 socket 文件就像是远端机器的 "代理人" 一样。比如,如果我们想给远端服务发点什么东西,那就只需要对这个文件执行写操作就行了。

socket_api
那写到了这个文件之后,剩下的发送工作自然就是由操作系统内核来完成了。

既然是写给操作系统,那操作系统就需要提供一个地方给用户写。同理,接收消息也是一样。

这个地方就是 socket 缓冲区

用户发送消息的时候写给 send buffer(发送缓冲区)

用户接收消息的时候写给 recv buffer(接收缓冲区)

也就是说一个socket ,会带有两个缓冲区,一个用于发送,一个用于接收。因为这是个先进先出的结构,有时候也叫它们发送、接收队列

一个socket有两个缓冲区

怎么观察 socket 缓冲区

如果想要查看 socket 缓冲区,可以在linux环境下执行 netstat -nt 命令。

# netstat -nt
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0     60 172.22.66.69:22         122.14.220.252:59889    ESTABLISHED
这上面表明了,这里有一个协议(Proto)类型为 TCP 的连接,同时还有本地(Local Address)和远端(Foreign Address)的IP信息,状态(State)是已连接。

还有Send-Q 是发送缓冲区,下面的数字60是指,当前还有60 Byte在发送缓冲区中未发送。而 Recv-Q 代表接收缓冲区, 此时是空的,数据都被应用进程接收干净了。


TCP部分

【动图缓冲区的收发流程,TCP执行发收的流程】

我们在使用TCP建立连接之后,一般会使用 send 发送数据。

int main(int argc, char *argv[])
{
    // 创建socket
    sockfd=socket(AF_INET,SOCK_STREAM, 0))

    // 建立连接  
    connect(sockfd, 服务器ip信息, sizeof(server))  

    // 执行 send 发送消息
    send(sockfd,str,sizeof(str),0))  

    // 关闭 socket
    close(sockfd);

    return 0;
}
上面是一段伪代码,仅用于展示大概逻辑,我们在建立好连接后,一般会在代码中执行 send 方法。那么此时,消息就会被立刻发到对端机器吗?


执行 send 发送的字节,会立马发送吗?

答案是不确定!执行 send 之后,数据只是拷贝到了socket 缓冲区。至 什么时候会发数据,发多少数据,全听操作系统安排。

tcp_sendmsg 逻辑
在用户进程中,程序通过操作 socket 会从用户态进入内核态,而 send方法会将数据一路传到传输层。在识别到是 TCP协议后,会调用 tcp_sendmsg 方法。

// net/ipv4/tcp.c
// 以下省略了大量逻辑
int tcp_sendmsg()
{  
  // 如果还有可以放数据的空间
  if (skb_availroom(skb) > 0) {
    // 尝试拷贝待发送数据到发送缓冲区
    err = skb_add_data_nocache(sk, skb, from, copy);
  }  
  // 下面是尝试发送的逻辑代码,先省略     
}
在 tcp_sendmsg 中, 核心工作就是将待发送的数据组织按照先后顺序放入到发送缓冲区中, 然后根据实际情况(比如拥塞窗口等)判断是否要发数据。如果不发送数据,那么此时直接返回。


如果缓冲区满了会怎么办

前面提到的情况里是,发送缓冲区有足够的空间,可以用于拷贝待发送数据。

如果发送缓冲区空间不足,或者满了,执行发送,会怎么样?

这里分两种情况。

首先,socket在创建的时候,是可以设置是阻塞的还是非阻塞的。

int s = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
比如通过上面的代码,就可以将 socket 设置为非阻塞SOCK_NONBLOCK)。

当发送缓冲区满了,如果还向socket执行send

  • 如果此时 socket 是阻塞的,那么程序会在那干等、死等,直到释放出新的缓存空间,就继续把数据拷进去,然后返回

send阻塞
  • 如果此时 socket 是非阻塞的,程序就会立刻返回一个 EAGAIN 错误信息,意思是  Try again , 现在缓冲区满了,你也别等了,待会再试一次。

send非阻塞
我们可以简单看下源码是怎么实现的。还是回到刚才的 tcp_sendmsg 发送方法中。

int tcp_sendmsg()
{  
  if (skb_availroom(skb) > 0) {
    // ..如果有足够缓冲区就执行balabla
  } else {
    // 如果发送缓冲区没空间了,那就等到有空间,至于等的方式,分阻塞和非阻塞
    if ((err = sk_stream_wait_memory(sk, 
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭