无多线程的树莓派C项目中如何将socket阻塞状态作为执行条件
解决方案
核心逻辑适配
你遇到的阻塞问题完全可以用poll()函数解决,无需引入多线程,也不用大幅改动原有代码结构,完全匹配你需要的“等待socket数据时并行执行硬件检测”的需求。
步骤1:引入头文件
在代码头部添加poll对应的头文件:
#include <poll.h>
步骤2:修改work()函数实现
将原有的直接调用read()的逻辑改为先通过poll()监听socket可读事件,设置短超时,超时时间内无socket数据则执行硬件检测逻辑:
void work() { char bs[1]; int n; struct pollfd sock_poll = { .fd = Sockfd, .events = POLLIN, // 监听socket可读事件 }; // 等待10ms,超时返回0,超时时间可根据硬件响应需求调整 int poll_ret = poll(&sock_poll, 1, 10); if (poll_ret < 0) { // poll调用出错,判定为连接异常 checkForSOT(); return; } else if (poll_ret == 0) { // 无socket数据,执行硬件按钮检测逻辑 static int oldI = 0; int i = digitalRead(iTSW); if((i ^ oldI) == 0 && oldI == 1) { testing = true; } else if((i ^ oldI) == 1 && oldI == 0) { testing = false; } if(testLoaded && usingTermCtrl && i && !testing) { RunTp(false); } return; } // 有socket数据到达,执行原有读取逻辑 n = read(Sockfd, bs, 1); if(n > 0) { doAct(bs[0]); } else { checkForSOT(); } }
可选方案:切换为非阻塞socket
如果需要完全不用阻塞调用,可在openPort()函数中拿到Sockfd后添加如下代码,将socket设为非阻塞模式:
#include <fcntl.h> // 放在Sockfd = newsockfd; 之后 fcntl(Sockfd, F_SETFL, O_NONBLOCK);
之后调用read()时如果返回-1且errno等于EAGAIN或EWOULDBLOCK,说明当前无数据可读,直接执行硬件检测逻辑即可。
学习资料参考
你正在看的Beej's网络编程指南,对应查阅第7章《Slightly Advanced Techniques》下的Blocking、poll()、select()小节即可,里面有这几个API的详细用法和适用场景说明。
NetBeans 12 远程调试树莓派配置步骤
- 树莓派端安装依赖:执行
sudo apt install gdbserver openssh-server,开启SSH服务并记住树莓派的IP地址、登录用户名和密码 - NetBeans端配置构建主机:打开项目,右键项目选择
属性->构建->构建主机->添加,输入树莓派的SSH连接信息,测试连通后设为默认构建主机 - 配置调试参数:右键项目选择
属性->运行,调试器类型选择GDB,远程调试命令填写gdbserver :<自定义端口> <程序在树莓派上的存储路径>,例如gdbserver :2345 /home/pi/hw_controller - 启动调试:先在树莓派端执行你填写的gdbserver命令,再点击NetBeans的调试按钮,连接成功后即可正常下断点调试代码
内容的提问来源于stack exchange,提问作者Greenwiz29
相关产品推荐
相关产品推荐

