阻塞IO下的echo实验

代码分析

echo代码位置:recipes-master/tpc/echo.cc echo_client.cc
服务端代码

int main(int argc, char* argv[])
{InetAddress listenAddr(3007);Acceptor acceptor(listenAddr);printf("Accepting... Ctrl-C to exit\n");int count = 0;bool nodelay = argc > 1 && strcmp(argv[1], "-D") == 0;while (true){TcpStreamPtr tcpStream = acceptor.accept();printf("accepted no. %d client\n", ++count);if (nodelay)tcpStream->setTcpNoDelay(true);// 一个线程处理一个客户端连接// C++11 doesn't allow capturing unique_ptr in lambda, C++14 allows.std::thread thr([count] (TcpStreamPtr stream) {printf("thread for no. %d client started.\n", count);char buf[4096];int nr = 0;while ( (nr = stream->receiveSome(buf, sizeof(buf))) > 0){int nw = stream->sendAll(buf, nr);if (nw < nr){break;}}printf("thread for no. %d client ended.\n", count);}, std::move(tcpStream));thr.detach();}
}

服务端的逻辑主要就是,建立连接,每次读取4096个字节,然后这些数据再返回给客户端。

客户端

int main(int argc, const char* argv[])
{if (argc < 3){printf("Usage: %s hostname message_length [scp]\n", argv[0]);return 0;}const int len = atoi(argv[2]);InetAddress addr(3007);if (!InetAddress::resolve(argv[1], &addr)){printf("Unable to resolve %s\n", argv[1]);return 0;}printf("connecting to %s\n", addr.toIpPort().c_str());TcpStreamPtr stream(TcpStream::connect(addr));if (!stream){printf("Unable to connect %s\n", addr.toIpPort().c_str());perror("");return 0;}printf("connected, sending %d bytes\n", len);// 发送数据std::string message(len, 'S');int nw = stream->sendAll(message.c_str(), message.size());printf("sent %d bytes\n", nw);if (argc > 3){for (char cmd : std::string(argv[3])){if (cmd == 's')  // shutdown{printf("shutdown write\n");stream->shutdownWrite();}else if (cmd == 'p') // pause{printf("sleeping for 10 seconds\n");::sleep(10);printf("done\n");}else if (cmd == 'c') // close{printf("close without reading response\n");return 0;}else{printf("unknown command '%c'\n", cmd);}}}// 返回数据std::vector<char> receive(len);int nr = stream->receiveAll(receive.data(), receive.size());printf("received %d bytes\n", nr);if (nr != nw){printf("!!! Incomplete response !!!\n");}
}

客户端的逻辑主要就是,建立连接,发送数据,数据发送完再接收读取返回的数据

测试

客户端在测试20m的数据时出现了阻塞,此时服务端也阻塞当中

[wang@localhost tpc]$ ./echo_client ip 2048000
connecting to 192.168.1.104:3007
connected, sending 2048000 bytes
# ... 客户端阻塞
[wang@localhost tpc]$ ./echo
Accepting... Ctrl-C to exit
accepted no. 1 client
thread for no. 1 client started.
# ... 服务端阻塞
排查问题

查看Recv-Q和Send-Q

服务端

[wang@localhost ~]$ netstat -tpn | grep '3007\|^[AP]'
(Not all processes could be identified, non-owned process infowill not be shown, you would have to be root to see it all.)
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp   536080 260640 192.168.1.104:3007      192.168.1.105:56412     ESTABLISHED 5985/./ech

客户端

[wang@localhost ~]$ netstat -tpn | grep '3007\|^[AP]'
(Not all processes could be identified, non-owned process infowill not be shown, you would have to be root to see it all.)
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp   261264 307992 192.168.1.105:56412     192.168.1.104:3007      ESTABLISHED 12526/./echo_client 

可以看见不管客户端还是服务端,Send-Q上都有大量的缓存数据,可以看出send发生阻塞。

分析原因

服务端:由于服务端在每次recv4K字节后需要send数据给客户端,但此时客户端正在send数据的过程中,没有recv数据,导致服务端send阻塞
客户端:由于服务端阻塞在send中,没有继续recv数据,导致客户端也陷入send阻塞当中

解决方案

我们在设计协议的时候,可以先让客户端发一个header,告诉服务端数据的长度,然后服务端在接收到header后,准备好一个符合大小的buffer,将数据全部读取到buffer当中,之后再返回数据给客户端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/3996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解释JDK、JRE和JVM的区别

JDK、JRE和JVM是Java编程语言中非常重要的三个组成部分&#xff0c;它们协同工作&#xff0c;使得Java程序能够在各种不同的平台上执行。下面详细解释这三者&#xff1a; JVM&#xff08;Java Virtual Machine&#xff09; JVM是Java虚拟机的缩写&#xff0c;它是一个虚拟的计…

Elasticsearch知识点表格总结

最近其实有点忙&#xff0c;在主攻Django项目和go语言项目&#xff0c;所以只能利用下班晚上和周末总结一些知识点&#xff0c;因为最近的公司的项目没有用上Elasticsearch&#xff0c;所以总结一下&#xff0c;方便以后复习&#xff0c;以及以后面试会用上&#xff0c;不然过段…

C# WinForm —— 09 标签、文本框、按钮控件

标签 Label 一般显示不能编辑的文本或图像 常用属性、事件&#xff1a; 属性用途(Name)标签对象的ID&#xff0c;在代码里引用标签的时候会用到,一般以 lbl 开头Text设置或获取 界面上显示的 文本信息Image显示图像ImageList图像集&#xff0c;通常和 ListView ToolStrip Tre…

【Linux网络编程】数据链路层

数据链路层 1.以太网帧格式2.重谈局域网转发的原理(基于协议)3.认识MTU3.1MTU对IP协议的影响3.2MTU对UDP协议的影响3.3MTU对于TCP协议的影响 4.ARP协议 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励…

【QT学习】9.绘图,三种贴图,贴图的转换,不规则贴图(透明泡泡),简单绘图工具制作

一。绘图的解释 Qt 中提供了强大的 2D 绘图系统&#xff0c;可以使用相同的 API 在屏幕和绘图设备上进行绘制&#xff0c;它主要基于QPainter、QPaintDevice 和 QPaintEngine 这三个类。 QPainter 用于执行绘图操作&#xff0c;其提供的 API 在 GUI 或 QImage、QOpenGLPaintDev…

【深度学习(1)】研0和研1如何上手深度学习及定方向

深度学习&#xff08;1&#xff09; 基础部分书籍鱼书 (理论部分) 视频课程我是土堆&#xff08;代码部分&#xff09; 提升部分李沐的动手学深度学习李沐老师的书 定方向网站&#xff1a; paperwithcode谷歌学术找论文 基础部分 书籍 鱼书 (理论部分) 适合入门&#xff0c;…

11.JAVAEE之网络原理1

1.应用层(和程序员接触最密切) 应用程序 在应用层这里,很多时候, 都是程序员"自定义"应用层协议的,(当然,也是有一些现成的应用层协议)&#xff08;这里的自定义协议,其实是非常简单的~~协议 >约定,程序员在代码中规定好,数据如何进行传输) 1.根据需求, 明确要传…

XTuner微调LLM:1.8B、多模态和Agent-笔记四

本次课程由XTuner 贡献者李剑锋、汪周谦、王群老师讲解【XTuner 微调 LLM&#xff1a;1.8B、多模态和 Agent】课程 课程视频&#xff1a;http:// https://b23.tv/QUhT6ni 课程文档&#xff1a;https://github.com/InternLM/Tutorial/blob/camp2/xtuner/readme.md 两种Finetun…

目标检测的mAP、PR指标含义

基本概念 什么是一个任务的度量标准。对于目标检测任务来说&#xff0c;它的首要目标是确定目标的位置并判别出目标类别。这里已医学图像为例&#xff0c;我们需要计算出血液红细胞&#xff08;RBC&#xff09;、白细胞&#xff08;WBC&#xff09;和血小板的数量。为了实现这一…

【网络安全】HTTP协议 — 基础

专栏文章索引&#xff1a;网络安全 有问题可私聊&#xff1a;QQ&#xff1a;3375119339 目录 学习目标​ 一、万维网的诞生与发展​编辑 1.万维网的诞生与发展 2.HTTP协议诞生与发展 二、网络基础 1.TCP/IP分层传输 1&#xff09;TCP/IP协议 2&#xff09;封装与拆封 …

stm32 hid自定义接收发送程序开发过程记录

cubleMX配置如下 修改端点描述符一次传输的数据大小 根据cubelMX标准在这里修改 编译错误 直接修改&#xff08;因为没有使用nodef &#xff09;编译通过 修改报告描述符&#xff08;默认的描述符无法传输数据&#xff09; 参考&#xff1a;USB协议详解第10讲&#xff08;USB描…

Xinlinx FPGA内的存储器BRAM全解

目录 一、总体概述1.7系列FPGA的BRAM特点2.资源情况 二、BRAM分类1.单端口RAM2.简单双端口RAM3.真双端口RAM 三、BRAM的读写1、Primitives Output Registers读操作注意事项2.三种写数据模式&#xff08;1&#xff09;Write_First&#xff08;2&#xff09;Read_First&#xff0…

Windows如何安装spark

Apache Spark是一个开源的大数据处理框架&#xff0c;旨在提供高效、通用和易用的大数据处理引擎。它最初由加州大学伯克利分校AMPLab开发&#xff0c;并于2010年开源。 Spark提供了一个基于内存的计算引擎&#xff0c;可以在大规模数据集上执行高速的数据处理任务。相比传统的…

pytest-stress:好用的pytest压力测试插件

简介&#xff1a;pytest-stress允许在用户定义的时间内循环测试。特别适用于一些已知测试时间&#xff0c;但不知道运行次数的场景。 历史攻略&#xff1a; 压力测试工具&#xff1a;Stress详解 Python&#xff1a;超过设定的时长则退出 安装&#xff1a; pip3 install py…

PC40与PC95磁芯的区别

磁芯pc95和pc40的差别在于PC95磁芯Pcv降低5%磁导率随温度变化小于PC40&#xff0c;利于谐振低温特性好,用在电源产品中低温效率高。另外就是PC95价格高。 PC是TDK公司对磁芯材料的命名&#xff0c; 类似有PC40&#xff0c;PC44&#xff0c;PC95&#xff0c;数字越大价格越高&am…

JetBrains CLion v2023.3.4 激活版 (C/C++ 集成开发IDE)

前言 JetBrains CLion是一款跨平台的C/C集成开发环境&#xff0c;由JetBrains公司推出。其最新版本支持C14几乎完全&#xff0c;并初步支持C17&#xff0c;使得编写代码更加便捷。CLion还提供了Disassembly view&#xff08;反汇编视图&#xff09;&#xff0c;即使没有源代码…

Unity 点击无效的问题

问题 我需要点击下落的音符。这个音符是一个按钮。但是点击一直没有触发这是为什么呢 Button unity的button事件button.onClick.AddListener因为我的音符下落太快&#xff0c;当按钮落下的时候&#xff0c;点击在音符上&#xff0c;但是抬起来的时候不在音符上【因为下落太快…

一、Django 初识

简介 Django 是一个用于构建 Web 应用程序的高级 Python Web 框架。 版本对应 不同版本的django框架是基于特定的不同的python版本开发的&#xff0c;所以不同版本的django框架要正常执行功能只能安装特定的python版本 Django安装 安装 Django # 全局安装 pip install dj…

web自动化系列-selenium的下拉框定位(十三)

在功能操作过程中 &#xff0c;遇到下拉列表是很正常的事 &#xff0c;比如像一些查询条件就都是使用的是下来列表 。所以 &#xff0c;selenium也需要支持对下拉框的操作 。 1.下拉列表 在selenium中&#xff0c;也提供了一个下拉列表操作的类 &#xff1a;Select . 以下为该…

设计模式入门(三)单例模式

文章目录 前提单例模式概念应用场景应用懒汉式饿汉式 参考链接 前提 最近在实际项目中使用到了设计模式中的单例模式&#xff0c;之前也单纯地从理论方面学习过单例模式&#xff0c;但是一直没有机会实际应用到项目中&#xff0c;这次从项目入手简单地对单例模式进行总结。 单…