当使用代码如下,测试的时候发现收到的串口数据有时会被分段。
unsigned char readBuf[128] = { 0 };
int receive_byte = 0;
int read_len = 0;
do
{
read_len = read(fd, readBuf + receive_byte, sizeof(readBuf) - receive_byte);
if (read_len > 0)
{
receive_byte += read_len;
}
} while (read_len > 0);
有看到网上说可以指定要获取的长度,一直循环获取到该长度。或者获取到指定的标志位之类。但是我这因为设备上协议已经固定,没有特别的标志位,数据还是变长的,并不主动上报消息,只有在下发指令后要及时获取回应的消息,所以这些方法都不太适用。只好给了个合适的时间段,获取该时间段内收到的数据。
代码使用了异步,发消息和收消息是两个线程。
发消息的时候设置标志位通知开始收,因为我这有多个串口,所以用map记录了标志位
nSendByte = write(fd, pData, dataLen);
{
boost::mutex::scoped_lock locker(m_mutexStartReadSerial);
m_mapStartReadSerial[strPortName] = true;
}
收消息的时候标志位读数组中相应串口的标志位,为true就开始计时并循环收消息,直到规定的时间为止,因为我收到的数据都不长,所以给了50ms的时间,此处可根据收到数据量的多少调整时间长度
unsigned char readBuf[128] = { 0 };
int32_t timeOutMs = 50;
bool bStartReadSerial = false;
while (!m_fini)
{
{
boost::mutex::scoped_lock locker(m_mutexStartReadSerial);
if (m_mapStartReadSerial.find(strPortName) != m_mapStartReadSerial.end())
{
bStartReadSerial = m_mapStartReadSerial[strPortName];
}
}
if (bStartReadSerial)
{
int receive_byte = 0;
int read_len = 0;
boost::xtime tstart, tend;// 时间对象
boost::xtime_get(&tstart, boost::TIME_UTC_); // 获取当前时间
double dIntervalMs = 0;
do
{
read_len = read(fd, readBuf + receive_byte, sizeof(readBuf) - receive_byte);
if (read_len > 0)
{
receive_byte += read_len;
}
boost::xtime_get(&tend, boost::TIME_UTC_);
uint64_t t = (tend.sec - tstart.sec - 1) * 1000 + (tend.nsec + 1000000000 - tstart.nsec) / 1000000;
dIntervalMs = (double)t;
} while (dIntervalMs < timeOutMs);
if (receive_byte > 0)
{
boost::mutex::scoped_lock locker(m_mutexSerialReadMsg);
m_serialReadMsg[strPortName].assign((char*)readBuf, receive_byte);
}
{
boost::mutex::scoped_lock locker(m_mutexStartReadSerial);
m_mapStartReadSerial[strPortName] = false;
}
}
else
{
boost::xtime m_xt;
boost::xtime_get(&m_xt, boost::TIME_UTC_);
m_xt.nsec += 20000000;
boost::thread::sleep(m_xt);
}
}
测试后发现能正常运行。