串口发送重发超时重发思路


       #region 串口发送
        //str 是发送的字符,retry_num 是重发次数timeout 是超时时间
        public bool UartSend(string str,UInt32 retry_num, UInt32 timeout)
        {
            try
            {
                myUart.IsReceive = false;//发送数据前重置接收标志
                for (int i = 0; i < retry_num; i++)
                {
                    myUart.UartSerialPort.Write(str);//串口发送数据
                    while (myUart.IsReceive == false)
                    {
                        Thread.Sleep(10);
                        count++;
                        if (count >= timeout / 10)
                            break;
                    }
                    if (count < timeout / 10) //如果在规定的时间内收到了应答,则直接返回,如果没有应答则继续重发
                        return true;

                    WriteLog(Brushes.Red, $"发送次数 + {i} \r\n");

                    count = 0;
                }

                return false;//如果发送次数超过3次,依然没有收到应答,则认为发送指令失败
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }
        }
        #endregion

```c
  private void ModbusPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                Thread.Sleep(100);//延缓一会,用于防止硬件发送速率跟不上缓存数据导致的缓存数据杂乱
                int len = UartSerialPort.BytesToRead;
                Byte[] readBuffer = new Byte[len];
                UartSerialPort.Read(readBuffer, 0, len); //将数据读入缓存
                if(readBuffer[0] == 49 && readBuffer[1] == 50 && readBuffer[2] == 51)//如果收到了"123"字符,则认为收到应答
                    IsReceive = true;
            }
            catch (Exception exception)
            {
                //MessageBox.Show(exception.Message);
            }
        }


设置一个定时器,发送的时候,打开定时器,同时计算时间,定时3秒内,在定时器中断中改变状态。类似长按短按的功能。

在 Linux C 语言中,可以使用套接字选项 `SO_RCVTIMEO` 和 `SO_SNDTIMEO` 来设置接收和发送超时时间。如果在指定时间内没有收到数据或者数据没有被成功发送,那么就会触发超时重发机制。 具体实现步骤如下: 1. 设置超时时间 使用 `setsockopt()` 函数来设置套接字选项 `SO_RCVTIMEO` 和 `SO_SNDTIMEO`,例如: ``` struct timeval timeout; timeout.tv_sec = 5; // 超时时间为 5 秒 timeout.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { perror("setsockopt"); exit(EXIT_FAILURE); } if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { perror("setsockopt"); exit(EXIT_FAILURE); } ``` 2. 发送数据 使用 `sendto()` 函数发送数据,例如: ``` if (sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, addrlen) < 0) { perror("sendto"); exit(EXIT_FAILURE); } ``` 3. 接收数据 使用 `recvfrom()` 函数接收数据,例如: ``` if (recvfrom(sockfd, buf, len, 0, (struct sockaddr *)&src_addr, &addrlen) < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) { // 超时,进行重发操作 if (sendto(sockfd, buf, len, 0, (struct sockaddr *)&dest_addr, addrlen) < 0) { perror("sendto"); exit(EXIT_FAILURE); } } else { perror("recvfrom"); exit(EXIT_FAILURE); } } ``` 在上面的代码中,如果 `recvfrom()` 函数返回的错误码是 `EWOULDBLOCK` 或者 `EAGAIN`,那么说明接收超时,此时可以进行重发操作。如果返回的错误码是其他值,那么说明接收出错,需要退出程序。 需要注意的是,超时时间的设置应该根据具体情况来确定,如果设置得太短,会频繁触发重发机制,影响性能;如果设置得太长,会增加数据传输的延迟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值