用实际案例来理解netstat -nao中的Recv-Q和Send-Q

2024-02-06 12:18

本文主要是介绍用实际案例来理解netstat -nao中的Recv-Q和Send-Q,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       我们先来看看:

 

xxxxxx$ netstat -ano | head             
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
tcp        0      0 127.0.0.1:42222         0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:48369     0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:13942     0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:10586     0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:63227     0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:8765            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:20126     0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 10.100.70.140:23456     0.0.0.0:*               LISTEN      off (0.00/0/0)

       第二列表内核recv缓冲区中的字节数(接收缓冲区), 第三列表示内核send缓冲区中的字节数(发送缓冲区)。 所以, 对于一个tcp连接的两端而言, 有四个内核缓冲区。

 

 

       来看程序, 服务端:

 

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>int main()
{int sockSrv = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_addr.s_addr = INADDR_ANY; addrSrv.sin_port = htons(8765);bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));listen(sockSrv, 5);struct sockaddr_in addrClient;int len = sizeof(struct sockaddr_in);int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, (socklen_t*)&len);while(1)    {    getchar();    char szRecvBuf[1001] = {0};    int iRet = recv(sockConn, szRecvBuf, sizeof(szRecvBuf) - 1, 0);    printf("iRet is %d\n", iRet);     }getchar();close(sockConn);close(sockSrv);return 0;
}

       客户端:

 

 

#include <unistd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <fcntl.h>int main()
{int sockClient = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addrSrv;addrSrv.sin_addr.s_addr = inet_addr("10.100.70.140");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(8765);connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));#define N 2000char szSendBuf[N] = {0};for(unsigned int i = 0; i < N; i++) //×Ö·ûÊý×é×îºóÒ»¸ö×Ö·û²»ÒªÇóÊÇ¡®\0¡¯{szSendBuf[i] = 'a';	}int total = 0;while(1){int iRet = send(sockClient, szSendBuf, sizeof(szSendBuf) , 0); total += iRet;printf("iRet is %d, total send is %d\n", iRet, total);getchar();}close(sockClient);return 0;
}

       我们先开启服务端, 再看起客户端, 此时客户端给服务端发送了2000字节, 但服务端没有去取出这2000字节, 我们来看看服务端的情况:

 

 

xxxxxx$ netstat -ano | grep 8765
tcp        0      0 0.0.0.0:8765            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp     2000      0 10.100.70.140:8765      10.100.70.139:43634     ESTABLISHED off (0.00/0/0)

       再看看客户端, 客户端都发送完了, 没有字节积压, 所以发送缓冲区中么有字节, 如下:

 

xxxxxx$ netstat -ano | grep 8765
tcp        0      0 10.100.70.139:43634     10.100.70.140:8765      ESTABLISHED off (0.00/0/0)

       
        此时, 如果我们在服务端用recv函数取出1000字节, 会怎样呢?  显然, 内核缓冲区中还剩100字节, 如下:

 

xxxxxx$ netstat -ano | grep 8765
tcp        0      0 0.0.0.0:8765            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp     1000      0 10.100.70.140:8765      10.100.70.139:43634     ESTABLISHED off (0.00/0/0)

 


        如何才能在客户端上看到内核缓冲区中的数据呢? 很简单, 让客户端一只发发发, 服务端的内核缓冲区数据塞满后, 自然开始在客户端的内核缓冲区积压了。 有兴趣的朋友可以试试, 这对理解tcp很有帮助。

 

 

       

 


 

这篇关于用实际案例来理解netstat -nao中的Recv-Q和Send-Q的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684282

相关文章

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

利用Python操作Word文档页码的实际应用

《利用Python操作Word文档页码的实际应用》在撰写长篇文档时,经常需要将文档分成多个节,每个节都需要单独的页码,下面:本文主要介绍利用Python操作Word文档页码的相关资料,文中通过代码... 目录需求:文档详情:要求:该程序的功能是:总结需求:一次性处理24个文档的页码。文档详情:1、每个

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

Java 中的 equals 和 hashCode 方法关系与正确重写实践案例

《Java中的equals和hashCode方法关系与正确重写实践案例》在Java中,equals和hashCode方法是Object类的核心方法,广泛用于对象比较和哈希集合(如HashMa... 目录一、背景与需求分析1.1 equals 和 hashCode 的背景1.2 需求分析1.3 技术挑战1.4

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java 正则表达式的使用实战案例

《Java正则表达式的使用实战案例》本文详细介绍了Java正则表达式的使用方法,涵盖语法细节、核心类方法、高级特性及实战案例,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录一、正则表达式语法详解1. 基础字符匹配2. 字符类([]定义)3. 量词(控制匹配次数)4. 边

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C