我收到许多来信,都问我为什么Read函数只读几个字节 ,我都快被问晕了。
当然这不是我的库的问题,这是很基本的通讯问题,因为通讯中传输需要时间,当你选择异步模式时你应该注意,这时候Read函数是非阻塞状态,意味着Read函数会迅速扫描缓冲区,把缓冲区里的字节读出来,这时候缓冲区里有多少字节就读多少字节,字节的多少取决于通讯速度与你计算机速度,你通讯越快,读得越多,计算机越快读得越少,这个容易理解吧。
所以这个不是一个问题,不需要执著于它,但是你如何实现应用?
我告诉你一个方案:
比如你有一个业务,一个仪表设备不停的发送数据给计算机,格式为"/x2 /xXX /xXX ............ /x3"
其中'/x2'是开始标志, '/x3'是结束标志, '/xXX'是数据,长度不定,也许1k 也学2k,假设数据不会出现标识位,那么程序应该这么写:
class MyComm : public cnComm
{
virtual void OnReceive()
{
static char buffer[8192];//临时缓冲区
static int buffer_index = 0;//数据索引,指向需要插入数据的点
buffer_index += Read(buffer+buffer_index, 8192-buffer_index);
char *find_ptr = std::find(buffer, buffer+buffer_index, '/x2');//查找开始标志
if(find_ptr != buffer+buffer_index)//找到开始标志
{
char * find_end_ptr = std::find(find_ptr, buffer+buffer_index, '/x3');//查找结束标志
if(find_end_ptr != buffer+buffer_index)//找到结束标志
{
char* data_buffer = new char[find_end_ptr-find_ptr+1];
std::copy(data_buffer, find_ptr, find_end_ptr+1);//拷贝数据
PostMessage(_hNotifyWnd, WM_DATA_COME, (WPARAM)data_buffer, 0);
//发送数据到主窗口去处理
std::copy(find_end_ptr+1, buffer+buffer_index, buffer);//删除
buffer_index = buffer+buffer_index-find_end_ptr-1;//修正插入数据的点数据索引
}
else
{
if(buffer_index == 8192)
{
//说明缓冲区溢出, 你要报错!
}
}
}
else 找不到标志
{
//说明通讯中存在垃圾数据,要清除它,留出缓冲区
buffer_index = 0;//注这里标识位只有一个字节所以全部删除
//如果标识位>1个字节, 比如开始标志为"/x2/xa/xb"
//程序就要这么写:
//std::copy(buffer+buffer_index-2, buffer+buffer_index, buffer);
//buffer_index = 2;
}
}
public:
};
看明白,里面有用到C++的标准库,代码只是示意,没有测试,但是逻辑和意识是正确的。
我看到好多人认为这个问题指责我的库,希望以后不会有,还有人建议用国外的,呵呵,没关系,不用就不用,我这也是方便又需要的人,对我自己来说,并没有太多的必要,谢谢!