linux串口客户端编程,【linux】串口编程(二)——非阻塞接收

项目中很少会使用阻塞接收,一般都是select+read监听模式来实现非阻塞接收。

使用selece时,需要处理一些异常情况的返回,比如:系统中断产生EINTR错误;超时错误ETIMEDOUT。

使用read时,需要处理读取时可能出现的错误,比如:对方关闭连接(ECONNRESET),连接被拒绝(ECONNREFUSED),文件描述符错误(EBADF)等

下面以libmodbus中receive_msg函数为例,总结select+read的处理步骤,其中有对modbus协议处理的步骤(2、7、8、9),如果不关心modbu协议可忽略这些步骤。

【0】函数返回值说明:

等待服务器的响应或客户端的请求。如果没有应答这个函数将会阻塞(超时);

如果接收uint8_t的消息数组成功,将会返回接收字符的个数,否则将会返回-1,并且errno将会被置为如下值:

ECONNRESET:对方复位连接

EMBBADDATA:无效数据

ETIMEDOUT:超时

read()和recv()函数的错误码

static int receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)

{

int rc;

fd_set rfds;

struct timeval tv;

struct timeval *p_tv;

int length_to_read;

int msg_length = 0;

_step_t step;

【1】设置fd_set

FD_ZERO(&rfds);

FD_SET(ctx->s, &rfds);

【2】分步接收并解析modbus的消息,首先接收功能码,并解析

step = _STEP_FUNCTION;

length_to_read = ctx->backend->header_length + 1;

【3】设置超时时间,根据服务器和客户端所传参数中的msg_type不同,做不同设置

---------- Request Indication ----------

| Client | ---------------------->| Server |

---------- Confirmation Response ----------

MSG_INDICATION:用在服务器端,一直等待,直到有客户端发起请求

MSG_CONFIRMATION:用在客户端,有等待超时

if (msg_type == MSG_INDICATION) {

/* 一直等待客户端的请求 */

p_tv = NULL;

} else {

tv.tv_sec = ctx->response_timeout.tv_sec;

tv.tv_usec = ctx->response_timeout.tv_usec;

p_tv = &tv;

}

【4】循环接收读取消息

while (length_to_read != 0) {

【5】select等待接收

while ((rc = select(ctx->s+1, rfds, NULL, NULL, p_tv)) == -1) {

if (errno == EINTR) {

//捕捉到一个非阻塞信号,c

FD_ZERO(rfds);

FD_SET(ctx->s, rfds);

}

}

if (rc == 0) {

//超时

errno = ETIMEDOUT;

rc = -1;

}

if (rc == -1) {

_error_print(ctx, "select");

if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {

int saved_errno = errno;

if (errno == ETIMEDOUT) {

_sleep_and_flush(ctx);

} else if (errno == EBADF) {

modbus_close(ctx);

modbus_connect(ctx);

}

errno = saved_errno;

}

return -1;

}

【6】接收消息

rc = read(ctx->s, msg + msg_length, length_to_read);

if (rc == 0) {

errno = ECONNRESET;

rc = -1;

}

if (rc == -1) {

//read错误

if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&

(errno == ECONNRESET || errno == ECONNREFUSED ||

errno == EBADF)) {

int saved_errno = errno;

modbus_close(ctx);

modbus_connect(ctx);

/* Could be removed by previous calls */

errno = saved_errno;

}

return -1;

}

//收到的总字节数

msg_length += rc;

//计算剩余的字节

length_to_read -= rc;

【7】分步接收modbus消息,判断当前步骤是否接收完,并进入下一步

if (length_to_read == 0) {

switch (step) {

【7.1】功能码接收完毕,根据功能码计算下一步的长度。

下一步标记为:meta,意为元或可变之意,因为该步骤的信息不固定

case _STEP_FUNCTION:

length_to_read = compute_meta_length_after_function(

msg[ctx->backend->header_length],

msg_type);

if (length_to_read != 0) {

step = _STEP_META;

break;

} //else:如果是其他的值,不break,直接转到下一步

【7.2】meta接收完毕,根据功能码和meta信息,计算下一步数据长度

case _STEP_META:

length_to_read = compute_data_length_after_meta(

ctx, msg, msg_type);

if ((msg_length + length_to_read) > ctx->backend->max_adu_length) {

errno = EMBBADDATA;

//接收数据太多,异常

return -1;

}

step = _STEP_DATA;

break;

default:

break;

}

}

【8】如果数据没有接收完毕,并且设置了字符间隔,则使用字符间隔作为超时来继续等待接收

if (length_to_read > 0 && ctx->byte_timeout.tv_sec != -1) {

tv.tv_sec = ctx->byte_timeout.tv_sec;

tv.tv_usec = ctx->byte_timeout.tv_usec;

p_tv = &tv;

}

}

【9】检查完整性

return ctx->backend->check_integrity(ctx, msg, msg_length);

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园整体解决方案是响应国家教育信息化政策,结合教育改革和技术创新的产物。该方案以物联网、大数据、人工智能和移动互联技术为基础,旨在打造一个安全、高效、互动且环保的教育环境。方案强调从数字化校园向智慧校园的转变,通过自动数据采集、智能分析和按需服务,实现校园业务的智能化管理。 方案的总体设计原则包括应用至上、分层设计和互联互通,确保系统能够满足不同用户角色的需求,并实现数据和资源的整合与共享。框架设计涵盖了校园安全、管理、教学、环境等多个方面,构建了一个全面的校园应用生态系统。这包括智慧安全系统、校园身份识别、智能排课及选课系统、智慧学习系统、精品录播教室方案等,以支持个性化学习和教学评估。 建设内容突出了智慧安全和智慧管理的重要性。智慧安全管理通过分布式录播系统和紧急预案一键启动功能,增强校园安全预警和事件响应能力。智慧管理系统则利用物联网技术,实现人员和设备的智能管理,提高校园运营效率。 智慧教学部分,方案提供了智慧学习系统和精品录播教室方案,支持专业级学习硬件和智能化网络管理,促进个性化学习和教学资源的高效利用。同时,教学质量评估中心和资源应用平台的建设,旨在提升教学评估的科学性和教育资源的共享性。 智慧环境建设则侧重于基于物联网的设备管理,通过智慧教室管理系统实现教室环境的智能控制和能效管理,打造绿色、节能的校园环境。电子班牌和校园信息发布系统的建设,将作为智慧校园的核心和入口,提供教务、一卡通、图书馆等系统的集成信息。 总体而言,智慧校园整体解决方案通过集成先进技术,不仅提升了校园的信息化水平,而且优化了教学和管理流程,为学生、教师和家长提供了更加便捷、个性化的教育体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值