问题引出

一个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秒。

最终放弃此方法。

  1. //示例代码
  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <termios.h>
  4. int kbhit(void) //return 0: no keyboard hit; return 1: keyboard hit
  5. {
  6. struct termios oldt, newt;
  7. int ch;
  8. int oldf;
  9. tcgetattr(STDIN_FILENO, &oldt);
  10. newt = oldt;
  11. newt.c_lflag &= ~(ICANON | ECHO);
  12. tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  13. oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  14. fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
  15. ch = getchar();
  16. tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  17. fcntl(STDIN_FILENO, F_SETFL, oldf);
  18. if(ch != EOF)
  19. {
  20. ungetc(ch, stdin);
  21. return 1;
  22. }
  23. return 0;
  24. }
  25. int main()
  26. {
  27. unsigned char line[128] = {0};
  28. unsigned char ch;
  29. unsigned int i = 0;
  30. while(1)
  31. {
  32. task_1(); //其它任务
  33. if(kbhit()) { //有键按下
  34. if((ch = getchar() != 0x0a) { //回车键没按下
  35. line[i++] = ch;
  36. } else { //回车键按下
  37. memset(line, 0, 128);
  38. i = 0;
  39. task_2(); //此处解析line数组内容
  40. }
  41. }
  42. }
  43. return 0;
  44. }

Method2

在进行select循环之前就把要输入的内容提前录入,然后回车。之后程序进入到select的标准输入可读流程,在这里使用fgets将之前录入的内容全部读入一个buf[],然后解析字符串,填入到发送报文;即只要不输入回车键,程序就无法进入select的标准输入可读流程,自然不会影响2秒超时发保活包。

这种方法实验效果能达到题目要求。

Method3

fgets为行缓存IO函数,遇到回车键才把处理缓冲中的数据流。将标准输入流stdin改为无缓冲方式,这样只要有字符敲入(即使没有敲入回车)select就会监听到标准输入可读。在相应流程中使用getchar()将捕获的输入存放于buf[],然后退出流程继续监听。若捕获到0x0a,表明输入的结束,之后同方法2一样解析和发送。

这种方法实验效果也能达到题目要求。

    1. setvbuf(stdin, NULL, _IONBF, 0); //设置标准输入流为无缓存

有关fgets和fcntl的讨论-待整理更新的更多相关文章

  1. Python面试题整理-更新中

    几个链接: 编程零基础应当如何开始学习 Python ? - 路人甲的回答 网易云课堂上有哪些值得推荐的 Python 教程? - 路人甲的回答 怎么用最短时间高效而踏实地学习 Python? - 路 ...

  2. Beta 讨论分析——持续更新ing

    wonderland Beta 讨论分析 标签(空格分隔): 软工实践 wonderland 主要工作: info信息: 1.关联账号界面:hbb 2.标签检索界面:hbb 3.近期活跃度(cf.hd ...

  3. JS-JavaScript类库整理 [更新中...]

    老大.jQuery插件库 ——收集最全最新最好的jQuery插件 http://www.jq22.com/ 一.Moment.js ——JavaScript 日期处理类库 http://momentj ...

  4. markdown常用命令(持续整理更新...)

    编写使用的工具 VS Code 拥有丰富插件支持的代码编辑器,当然也支持markdown MdEditor一款在线编辑markdown网站 1.标题 示例: # 一级标题 ## 二级标题 ### 三级 ...

  5. 前端开发常用PhotoShop快捷键整理(更新中)

    图片来源 UI提供的psd图 印屏幕:PrScrn SysRq(键盘按键) 浏览器(插件)获取 常用的快捷键: 新建 Ctrl + N 取消选框 Ctrl + D 反选 Ctrl + shift + ...

  6. IdentityServer4笔记整理(更新中)

    1 OAuth 2.0 1.1 OAuth 2.0协议流程图 1.2 授权码模式 1.3 简化模式 1.4 资源所有者密码模式 1.5 客户端凭证模式 2 OpenID Connect(OIDC) 2 ...

  7. JavaEE error整理(不断更新)

    该文章用于整理开发中遇到的一些错误,及解决方法,不断整理更新. 1. 缺包异常 异常1:java.lang.NoClassDefFoundError: org/apache/commons/loggi ...

  8. TypeScript 基础知识点整理

    一.TypeScript的特点 1.支持ES6规范 2.强大的IDE支持(集成开发环境) 允许为变量指定类型,减少你在开发阶段犯错误的几率. 语法提示,在IDE编写代码时,它会根据你所处的上下文把你能 ...

  9. 重新整理 mysql 基础篇————— 介绍mysql[一]

    前言 准备整理mysql的基础篇了,前面整理了sql语句序列的的<sql 语句系列(八百章)>,感觉很多用不上,就停下来了,后续还是会继续整理. mysql 基础篇主要是对一些基础进行整理 ...

随机推荐

  1. 数据库MySQL一

    P252 1.MySQL 最为主要使用的数据库 my sequel 不容易查找数据 DB数据库 存储数据的仓库,它保存了一系列有组织的数据 DBMS数据库管理系统,数据库是通过DBMS创建和操作的容器 ...

  2. IDEA创建XML文件没有Spring Config选项

    我在resources目录下导入3个配置文件时,applicationContext-common.xml文件中有4处http地址红色报错,下图为修正后的图片 了解到可能是由于父工程的pom文件中没有 ...

  3. 树莓派WIFI

    树莓派WIFI设置 在"开始使用树莓派"中,我们在boot根目录下创wpa_supplicant.conf文件,实现了第一次连接wifi.以后开机后,树莓派会自动连接那个wifi. ...

  4. 【笔记】《Redis设计与实现》chapter18 发布与订阅

    chapter18 发布与订阅 客户端订阅频道. 客户端向频道发送消息, 消息被传递至各个订阅者. 匹配模式 客户端订阅模式. 客户端向频道发送消息, 消息被传递给正在订阅匹配模式的订阅者. 另一个模 ...

  5. isAssignableFrom与instanceof

    isAssignableFrom()方法与instanceof关键字的区别总结为以下两个点: isAssignableFrom()方法是从类继承的角度去判断,instanceof关键字是从实例继承的角 ...

  6. Typora配置PicGo时,提示Failed to fetch【Bug集中营】

    Typora配置PicGo时,提示Failed to fetch 两者配置的端口不一致造成的 打开Typora,选择文件-偏好设置-图像-验证图片上传选项,点击验证图片上传选项 会提示错误:Faile ...

  7. Python 基础教程 —— 网络爬虫入门篇

    前言 Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言,它由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年.自面世以后,Pytho ...

  8. 077 Kuchiguse

    The Japanese language is notorious for its sentence ending particles. Personal preference of such pa ...

  9. 支持rotate和大小限制的golang log库

    支持大小限制和rotate的log库,还是很有必要的,前者让你不再操心磁盘被吃光,后者让查日志更方便. 但是在golang中没有太好的实现,看过一些开源的和自行实现的,都有几个不满意的地方,比如: 没 ...

  10. CPF 入门教程 - 属性和事件(七)

    CPF C#跨平台桌面UI框架 系列教程 CPF 入门教程(一) CPF 入门教程 - 数据绑定和命令绑定(二) CPF 入门教程 - 样式和动画(三) CPF 入门教程 - 绘图(四) CPF 入门 ...