有关fgets和fcntl的讨论-待整理更新
问题引出
一个client程序:select 超时监听 sockfd套接字 和 STDIN_FILENO标准输入:若sockfd可读则接收server报文;若标准输入可读(按下回车),则开始用fgets/fscanf等函数从标准输入捕获字符后发送给server;若select 2秒超时,client发送一次心跳包给server。要求不能开其他的进程或线程,也不能使用定时器和信号,即单线程client。
现在问题来了,在使用fgets/fscanf时,会阻塞select函数,这样一来client就无法进入超时流程发送心跳包;若将标准输入设置为非阻塞,那么fgets/fscanf立即返回,捕获的内容为空,达不到要求。
请问,有没有一种方法能让程序一边等待fgets/fscanf的捕获,一边循环非阻塞执行select函数?
尝试方法
Method1
用过linux下实现的kbhit,若没有按键输入则跳出这个函数,有输入则getchar到一个数组中存放然后退出函数,若捕获到回车键再把数组内容填充到发送报文。这样就是一个非阻塞的输入函数。
case1:select还是监听标准输入,只有按下回车键,程序才可能进入select的标准输入可读流程。这样要想输入一个字符必须先敲一个回车,显然不行。
case2:select不监听标准输入,在循环中,先执行select,再执行kbhit。这种方式能行,但是响应太慢,因为select是2秒超发心跳,所以select是半阻塞的,也就是说要想执行kbhit,必须等待2秒。
最终放弃此方法。
- //示例代码
- #include <stdio.h>
- #include <fcntl.h>
- #include <termios.h>
- int kbhit(void) //return 0: no keyboard hit; return 1: keyboard hit
- {
- struct termios oldt, newt;
- int ch;
- int oldf;
- tcgetattr(STDIN_FILENO, &oldt);
- newt = oldt;
- newt.c_lflag &= ~(ICANON | ECHO);
- tcsetattr(STDIN_FILENO, TCSANOW, &newt);
- oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
- fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
- ch = getchar();
- tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
- fcntl(STDIN_FILENO, F_SETFL, oldf);
- if(ch != EOF)
- {
- ungetc(ch, stdin);
- return 1;
- }
- return 0;
- }
- int main()
- {
- unsigned char line[128] = {0};
- unsigned char ch;
- unsigned int i = 0;
- while(1)
- {
- task_1(); //其它任务
- if(kbhit()) { //有键按下
- if((ch = getchar() != 0x0a) { //回车键没按下
- line[i++] = ch;
- } else { //回车键按下
- memset(line, 0, 128);
- i = 0;
- task_2(); //此处解析line数组内容
- }
- }
- }
- return 0;
- }
Method2
在进行select循环之前就把要输入的内容提前录入,然后回车。之后程序进入到select的标准输入可读流程,在这里使用fgets将之前录入的内容全部读入一个buf[],然后解析字符串,填入到发送报文;即只要不输入回车键,程序就无法进入select的标准输入可读流程,自然不会影响2秒超时发保活包。
这种方法实验效果能达到题目要求。
Method3
fgets为行缓存IO函数,遇到回车键才把处理缓冲中的数据流。将标准输入流stdin改为无缓冲方式,这样只要有字符敲入(即使没有敲入回车)select就会监听到标准输入可读。在相应流程中使用getchar()将捕获的输入存放于buf[],然后退出流程继续监听。若捕获到0x0a,表明输入的结束,之后同方法2一样解析和发送。
这种方法实验效果也能达到题目要求。
- setvbuf(stdin, NULL, _IONBF, 0); //设置标准输入流为无缓存
有关fgets和fcntl的讨论-待整理更新的更多相关文章
- Python面试题整理-更新中
几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...
- Beta 讨论分析——持续更新ing
wonderland Beta 讨论分析 标签(空格分隔): 软工实践 wonderland 主要工作: info信息: 1.关联账号界面:hbb 2.标签检索界面:hbb 3.近期活跃度(cf.hd ...
- JS-JavaScript类库整理 [更新中...]
老大.jQuery插件库 ——收集最全最新最好的jQuery插件 http://www.jq22.com/ 一.Moment.js ——JavaScript 日期处理类库 http://momentj ...
- markdown常用命令(持续整理更新...)
编写使用的工具 VS Code 拥有丰富插件支持的代码编辑器,当然也支持markdown MdEditor一款在线编辑markdown网站 1.标题 示例: # 一级标题 ## 二级标题 ### 三级 ...
- 前端开发常用PhotoShop快捷键整理(更新中)
图片来源 UI提供的psd图 印屏幕:PrScrn SysRq(键盘按键) 浏览器(插件)获取 常用的快捷键: 新建 Ctrl + N 取消选框 Ctrl + D 反选 Ctrl + shift + ...
- IdentityServer4笔记整理(更新中)
1 OAuth 2.0 1.1 OAuth 2.0协议流程图 1.2 授权码模式 1.3 简化模式 1.4 资源所有者密码模式 1.5 客户端凭证模式 2 OpenID Connect(OIDC) 2 ...
- JavaEE error整理(不断更新)
该文章用于整理开发中遇到的一些错误,及解决方法,不断整理更新. 1. 缺包异常 异常1:java.lang.NoClassDefFoundError: org/apache/commons/loggi ...
- TypeScript 基础知识点整理
一.TypeScript的特点 1.支持ES6规范 2.强大的IDE支持(集成开发环境) 允许为变量指定类型,减少你在开发阶段犯错误的几率. 语法提示,在IDE编写代码时,它会根据你所处的上下文把你能 ...
- 重新整理 mysql 基础篇————— 介绍mysql[一]
前言 准备整理mysql的基础篇了,前面整理了sql语句序列的的<sql 语句系列(八百章)>,感觉很多用不上,就停下来了,后续还是会继续整理. mysql 基础篇主要是对一些基础进行整理 ...
随机推荐
- 动态语言 VS 静态语言
静态语言 VS 动态语言 动态语言 是一类在运行时可以改变其结构的语言:例如新的函数.对象.甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化.通俗点说就是在运行时代码可以根据某些条件改变自 ...
- Java高级【Junit、反射、注解】
1.Junit单元测试 * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具体的执行流程. * Junit使用 ...
- 【CTF】2019湖湘杯 miscmisc writeup
题目来源:2019湖湘杯 题目链接:https://adworld.xctf.org.cn/task/answer?type=misc&number=1&grade=1&id= ...
- 关于Green AI
上一篇文章提到了模型不环保这个话题.这篇文章就这个问题展开唠叨一下. 自从BERT, GPT此类的大型模型诞生以来,小作坊们除了把pre-trained的模型拿过来微调一下,就束手无策了,因为成本实在 ...
- matlab数值类型
matlab数值类型 数值类型的分类 整数类型 整数类型有8种.上面的数字为其内存大小,如:int8,整数所占内存大小为8个字节.除了int64 和 uint64不能进行数值运算之外都可以. 类 ...
- 如何识别自己基因组数据是哪个全基因组参考版本(Genome Reference Versions/ Genome Build)
首先在这里先感谢我们[Bio生信学习交流群]的群友和创建此群的群主[陈博士后]. 今天解决的问题是怎么查看自己的基因组数据是哪个Genome Reference Versions. 步骤: 第一步,打 ...
- 在kubernetes上部署zookeeper,kafka集群
本文采用网上镜像:mirrorgooglecontainers/kubernetes-zookeeper:1.0-3.4.10 准备共享存储:nfs,glusterfs,seaweed或其他,并在no ...
- 【面试题2020-03-30】面试官:对并发熟悉吗?说说Synchronized及实现原理
一.Synchronized的基本使用 Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法. Synchronized的作用主要有三个: 1.确保线程互斥的访问同 ...
- POJ2983 查分约束系统
题意: 给你n个点,然后给你两种情况,P a b c,表明a在b的北边c那么远,V a b 表明a在b的北边(距离最少是1),问你这些条件是否冲突. 思路: 一开始想用带权并 ...
- Linux中环境变量的设置
目录 环境变量 Shell定义的环境变量 查看环境变量 Linux下环境变量的设置 环境变量 在Windows 系统下,很多软件安装都需要配置环境变量,比如 安装 jdk ,如果不配置环境变量,在非软 ...