Windows下实现COM口通信c++源代码(验证可行)

       近期接到一款新的硬件设备需要实现PC端与安卓终端实现COM口通信,以往都是厂家封装了通信模块或者采用Windows的SCARD读卡器设备,调用SCardConnectA、SCardTransmit等方法来实现通信。

      这一次比较惨,需要写个比较原始一点的。串口的连接和读写参考了如下地址:C++ 串口通讯(含所有源代码)_vivisl的博客-CSDN博客_串口通信代码

       本人在创建和数据读写上做了些许优化,采用新增写线程、读线程、和令牌回令机制来保证一应一答方便上层操作。秉着程序员天下为公,一切开源的念想,特将源码贴出望能给需要帮助之人提供些许的帮助。

-- -- -- -- -- 

头文件 DataTransmit.h

#ifndef __DATATRANSMIT__H__
#define __DATATRANSMIT__H__
#include<windows.h>
#include<deque>
#include<map>
/*
此文件实现com口端口通信操作
作者:王邵华
时间:2021/9/17
*/


//int reqid = (fd & 0xFF )<< 24 | (uid & 0x00FFFFFF)
//口令
typedef struct _SShibboleth
{
	int buffsize;
	const unsigned char *buff;
	_SShibboleth(const unsigned char *b,int s){buff=b;buffsize=s;}
	_SShibboleth(){}
}SShibboleth,*pSShibboleth;

//回令
typedef struct _SBackcross
{
	long long timestamp;
	int buffsize;
	unsigned char* buff;
	_SBackcross(unsigned char *b,int s,long long t){buff=b;buffsize=s;timestamp=t;}
	_SBackcross(){}
	~_SBackcross()
	{
		if(buff)
		{
			delete buff;
			buff = nullptr;
		}
	}
}SBackcross,*pSBackcross;

typedef struct _SComBuffer
{
	_SShibboleth shibboleth;
	_SBackcross  backcross;
	int shibbolethRet;
	int backcrossRet;
}SComBuffer,*pSComBuffer;

class CCOM
{
public:
	CCOM(int com,UINT  baud = 9600, char  parity = 'N', UINT  databits = 8, UINT  stopsbits = 1);
	virtual ~CCOM();
	HANDLE GetComHandle();
	/*
	WriteBuffer: 从PC端写入buff的buffsize个数据到终端
	params:
	in:
		const unsigned char *buff:写入数据指针,上传分配空间
		int buffsize:写入数据的长度
	out:
		int &reqid:此次请求的唯一ID,用于后续操作的令牌
	return:
		int:成功写入的长度,写入失败返回负数
	*/
	int WriteBuffer(const unsigned char *buff, int buffsize, int &reqid);
	/*
	ReadBufferLen: 获取终端回应该令牌的数据长度
	params:
	in:
		const int reqid:WriteBuffer调用时得到的令牌ID
	out:
	
	return:
		int:回令的长度,失败返回-1
	*/
	int ReadBufferLen(const int reqid);
	/*
	ReadBuffer: 从终端读取该令牌的回令数据
	params:
	in:
		const int reqid:WriteBuffer调用时得到的令牌ID
	out:
		unsigned char *buff:写入数据指针,上传分配空间
		int buffsize:写入数据的长度
	return:
		int:成功写入的长度,写入失败返回负数
	备注:
	    回令只能被读取一次,自动失效,超时未回令也会自动失效
	*/
	int ReadBuffer(const int reqid, unsigned char *buff, int buffsize);

	/*
	SetTimeout: 设置超时时间
	params:
	in:
		int time:超时时间,单位毫秒.时间不合法[20-300000]20毫秒-5分钟按默认6秒
	out:
		
	return:
		bool:成功true,失败false
	备注:
	    回令只能被读取一次,自动失效,超时未回令也会自动失效
	*/
	bool SetTimeout(int time){
		time = time * 1000;
		if(time>=20 && time <= 300000)timeout = time;
		else 
			timeout = 6000;
		return true;
	}

private:
	CCOM(const CCOM&){};
	CCOM(const  CCOM&&){};
	CCOM& operator=(const CCOM&){};
	CCOM& operator=(const CCOM&&){};

	static unsigned int __stdcall ListenReadThread(void* pParam);
    static unsigned int __stdcall ListenWriteThread(void* pParam);

	bool WriteComData(int reqid, const unsigned char* pData, unsigned int length);
	bool ReadComData(int reqid, unsigned char* pData, unsigned int length);
	void deleteReqidFront();
	unsigned int GetBytesInCOM();
	bool openPort(UINT portNo);
	bool InitPort(UINT portNo, const LPDCB& plDCB);
	/** 初始化串口函数
	*
	*  @param:  UINT portNo 串口编号,默认值为1,即COM1,注意,尽量不要大于9
	*  @param:  UINT baud   波特率,默认为9600
	*  @param:  char parity 是否进行奇偶校验,'Y'表示需要奇偶校验,'N'表示不需要奇偶校验
	*  @param:  UINT databits 数据位的个数,默认值为8个数据位
	*  @param:  UINT stopsbits 停止位使用格式,默认值为1
	*  @param:  DWORD dwCommEvents 默认为EV_RXCHAR,即只要收发任意一个字符,则产生一个事件
	*  @return: bool  初始化是否成功
	*  @note:   在使用其他本类提供的函数前,请先调用本函数进行串口的初始化
	*        /n本函数提供了一些常用的串口参数设置,若需要自行设置详细的DCB参数,可使用重载函数
	*           /n本串口类析构时会自动关闭串口,无需额外执行关闭串口
	*  @see:
	*/
	bool InitPort(UINT  portNo = 1, UINT  baud = CBR_9600, char  parity = 'N', UINT  databits = 8, UINT  stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR);
private:
	HANDLE  m_hComm;
	int m_comPort;
	int m_reqid;
	/** 线程句柄 */
	volatile HANDLE    m_hListenReadThread;
	volatile HANDLE    m_hListenWriteThread;
	unsigned int m_ListenReadThreadId;
	unsigned int m_ListenWriteThreadId;
	volatile HANDLE hEventListenReadThread; //开启读数据事件
	volatile HANDLE hEventListenWriteThread; //开启写数据事件
	volatile HANDLE hEventExit;
	char szEventListenReadThread[128], szEventListenWriteThread[128], szEventExit[128];
	bool isRun;

	int timeout;
	/** 同步互斥,临界区保护 */
	CRITICAL_SECTION   m_csSync;       //!< 互斥操作串口 
	std::deque<int> m_Reqid;
	std::map<int,SComBuffer> m_SComBuffer;
};





class CComHelper
{

public:
	HANDLE CreatePort(UINT  portNo = 1, UINT  baud = CBR_9600, char  parity = 'N', UINT  databits = 8, UINT  stopsbits = 1);
	bool RemovePort(HANDLE h);
	int Write(HANDLE h,const unsigned char *buff, int buffsize, int &reqid);
	int ReadLen(HANDLE h, const int reqid);
	int Read(HANDLE h, const int reqid, unsigned char *buff, int buffsize);
	bool SetTimeout(HANDLE h,int time);
	static CComHelper* getInstance();
	virtual ~CComHelper()
	{
		m_mapPortCom.erase(m_mapPortCom.begin(),m_mapPortCom.end());
	}
private:
	CComHelper(){};
	CComHelper(const CComHelper&){};
	CComHelper(const  CComHelper&&){};
	CComHelper& operator=(const CComHelper&){};
	CComHelper& operator=(const CComHelper&&){};

	std::map<UINT,CCOM*> m_mapPortCom;
	std::map<HANDLE,UINT> m_mapHandlePort;
	/*
	HANDLE h = CreatePort(3);
	unsigned char writebuff[5] = {0xAA,0AA,0XAA,0X99,0X96};
	int reqid = 0;
	int len = 0;
	int ret = 0;
	if(0 < Write(h, writebuff,5,reqid))
	{
		if(0 < (len =  ReadBufferLen(h,reqid)))
		{
			unsigned char *readbuff = new unsigned char[len];
			if(0 < Read(h,reqid,readbuff,len))
			{
				//	do your things
				//...
			}
			if(readbuff){delete[] readbuff; readbuff=nullptr;}
		}


	}
	if(INVALID_HANDLE_VALUE != h)
	{
		RemovePort(h);
	}
	*/
};
#endif

源文件 DataTransmit.cpp

#include "DataTransmit.h"
#include <stdio.h>
#include <process.h>


#define ERROR_DEFAULT -1
#define ERROR_NOEXECUTE -9999
#define ERROR_INVALID_HANDLE_VALUE -9988
#define ERROR_READORWRITE -9977
#define ERROR_UNCONNECTION -9966
#define ERROR_PARAMS -2


#define MAX_TIMEOUT 6000

CCOM::CCOM(int com, UINT  baud, char  parity, UINT  databits, UINT  stopsbits)
{
	m_comPort = com;
	m_reqid = 0;
	m_hComm = INVALID_HANDLE_VALUE;
	m_hListenReadThread = INVALID_HANDLE_VALUE;
	m_hListenWriteThread = INVALID_HANDLE_VALUE;
	hEventListenReadThread = INVALID_HANDLE_VALUE;
	hEventListenWriteThread  = INVALID_HANDLE_VALUE;
    //开启端口通信句柄
	if(InitPort(com,baud,parity,databits,stopsbits))
	{
		//创建读写线程
		m_hListenReadThread = (HANDLE)_beginthreadex(NULL, 0, ListenReadThread, this, 0, &m_ListenReadThreadId);
		m_hListenWriteThread = (HANDLE)_beginthreadex(NULL, 0, ListenWriteThread, this, 0, &m_ListenWriteThreadId);
	
		sprintf_s(szEventListenReadThread, "EventListenReadThread_COM%d_%d",com,m_hComm);
		sprintf_s(szEventListenWriteThread, "EventListenWriteThread_COM%d_%d",com,m_hComm);
		sprintf_s(szEventExit, "szEventExit_COM%d_%d",com,m_hComm);

		hEventListenReadThread = ::CreateEventA(NULL,true,false,szEventListenReadThread);
		hEventListenWriteThread = ::CreateEventA(NULL,true,false,szEventListenWriteThread);
		hEventExit =  ::CreateEventA(NULL,true,false,szEventExit);
	}
	::InitializeCriticalSection(&m_csSync);
	timeout = MAX_TIMEOUT;
}

bool CCOM::InitPort(UINT portNo, const LPDCB& plDCB)
{
	/** 打开指定串口,该函数内部已经有临界区保护,上面请不要加保护 */

	if (!openPort(portNo))
	{
		return false;
	}

	/** 配置串口参数 */
	if (!SetCommState(m_hComm, plDCB))
	{
		return false;
	}

	/**  清空串口缓冲区 */
	PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
	return true;
}

bool CCOM::openPort(UINT portNo)
{
	/** 把串口的编号转换为设备名 */
	char szPort[50];
	sprintf_s(szPort, "\\\\.\\COM%d", portNo);

	/** 打开指定的串口 */

	m_hComm = CreateFileA(szPort,  /** 设备名,COM1,COM2等 */
		GENERIC_READ | GENERIC_WRITE, /** 访问模式,可同时读写 */
		0,                            /** 共享模式,0表示不共享 */
		NULL,                         /** 安全性设置,一般使用NULL */
		OPEN_EXISTING,                /** 该参数表示设备必须存在,否则创建失败 */
		0,
		0);

	/** 如果打开失败,释放资源并返回 */
	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		return false;
	}	

	return true;
}

bool CCOM::InitPort(UINT portNo /*= 1*/, UINT baud /*= CBR_9600*/, char parity /*= 'N'*/,
	UINT databits /*= 8*/, UINT stopsbits /*= 1*/, DWORD dwCommEvents /*= EV_RXCHAR*/)

{
	/** 临时变量,将制定参数转化为字符串形式,以构造DCB结构 */
	char szDCBparam[50];
	sprintf_s(szDCBparam, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopsbits);

	/** 打开指定串口,该函数内部已经有临界区保护,上面请不要加保护 */
	if (!openPort(portNo))
	{
		return false;
	}

	/** 是否有错误发生 */
	BOOL bIsSuccess = TRUE;


	/** 在此可以设置输入输出的缓冲区大小,如果不设置,则系统会设置默认值.
	*  自己设置缓冲区大小时,要注意设置稍大一些,避免缓冲区溢出
	*/
	/*if (bIsSuccess )
	{
	bIsSuccess = SetupComm(m_hComm,10,10);
	}*/

	/** 设置串口的超时时间,均设为0,表示不使用超时限制 */
	COMMTIMEOUTS  CommTimeouts;
	CommTimeouts.ReadIntervalTimeout = 0;
	CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	CommTimeouts.ReadTotalTimeoutConstant = 0;
	CommTimeouts.WriteTotalTimeoutMultiplier = 0;
	CommTimeouts.WriteTotalTimeoutConstant = 0;

	if (bIsSuccess)
	{
		bIsSuccess = SetCommTimeouts(m_hComm, &CommTimeouts);
	}

	DCB  dcb;
	if (bIsSuccess)
	{
		/** 获取当前串口配置参数,并且构造串口DCB参数 */
		bIsSuccess = GetCommState(m_hComm, &dcb) && BuildCommDCB(szDCBparam, &dcb);
		/** 开启RTS flow控制 */
		dcb.fRtsControl = RTS_CONTROL_ENABLE;
	}

	if (bIsSuccess)
	{
		/** 使用DCB参数配置串口状态 */
		bIsSuccess = SetCommState(m_hComm, &dcb);
	}

	/**  清空串口缓冲区 */
	PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
	return bIsSuccess == TRUE;
}


#define CLOSEHANDLE(x) \
	if((x) != INVALID_HANDLE_VALUE)\
	{\
		::CloseHandle((x));\
		(x) = INVALID_HANDLE_VALUE;\
	}

CCOM::~CCOM()
{
	m_SComBuffer.erase(m_SComBuffer.begin(),m_SComBuffer.end());
	::SetEvent(hEventExit);
	::Sleep(200);
	::DeleteCriticalSection(&m_csSync);

	CLOSEHANDLE(m_hComm)
	CLOSEHANDLE(m_hListenReadThread)
	CLOSEHANDLE(m_hListenWriteThread)
	CLOSEHANDLE(hEventListenReadThread)
	CLOSEHANDLE(hEventListenWriteThread)
	CLOSEHANDLE(hEventExit)
}

HANDLE CCOM::GetComHandle()
{
	return m_hComm;
}

unsigned int __stdcall CCOM::ListenReadThread(void* pParam)
{
	CCOM *pSerialPort = reinterpret_cast<CCOM*>(pParam);
	HANDLE handles[2] = {pSerialPort->hEventListenReadThread,pSerialPort->hEventExit};
	while(true)
	{
		int waitobject = ::WaitForMultipleObjects(2,handles,false,INFINITE); //
		int errorno = ::GetLastError();
		switch (waitobject)
		{
		case WAIT_OBJECT_0:  //读数据
			{
				auto reqid = pSerialPort->m_Reqid.front();
				pSerialPort->deleteReqidFront();
				auto &itr = pSerialPort->m_SComBuffer.find(reqid);
	            if(itr == pSerialPort->m_SComBuffer.end()) break;

				long start = ::GetTickCount();
	        	long end = 0;
				unsigned int size = 0;
				while(size <= 0)
				{
					size = pSerialPort->GetBytesInCOM();
					end = ::GetTickCount();
					if(end - start > pSerialPort->timeout) break; //超时未应答
				}
				if(size <= 0) 
				{
					pSerialPort->m_SComBuffer[reqid].backcrossRet = ERROR_UNCONNECTION;
					break;
				}
				pSerialPort->m_SComBuffer[reqid].backcross.buff = new unsigned char[size];
				memset(pSerialPort->m_SComBuffer[reqid].backcross.buff,0x00,size);
				pSerialPort->m_SComBuffer[reqid].backcross.buffsize = size;
				pSerialPort->m_SComBuffer[reqid].backcross.timestamp = ::GetTickCount();
				pSerialPort->ReadComData(reqid,pSerialPort->m_SComBuffer[reqid].backcross.buff,pSerialPort->m_SComBuffer[reqid].backcross.buffsize);
				break;
			}
        case WAIT_OBJECT_0 + 1:  //结束
		{
			return 0;
			break;
		}
		default:
				break;
			
		}
		::ResetEvent(pSerialPort->hEventListenReadThread);
	}
	return 0;

}

unsigned int __stdcall CCOM::ListenWriteThread(void* pParam)
{
	CCOM *pSerialPort = reinterpret_cast<CCOM*>(pParam);
	HANDLE handles[2] = {pSerialPort->hEventListenWriteThread,pSerialPort->hEventExit};
	while(true)
	{
		int waitobject = ::WaitForMultipleObjects(2,handles,false,INFINITE); //
		int errorno = ::GetLastError();
		switch (waitobject)
		{
		case WAIT_OBJECT_0:  //写数据
			{
				auto reqid = pSerialPort->m_Reqid.front();
				//
				auto itr = pSerialPort->m_SComBuffer.find(reqid);
				if(itr != pSerialPort->m_SComBuffer.end())
				{
					if(pSerialPort->WriteComData(reqid, itr->second.shibboleth.buff,itr->second.shibboleth.buffsize))
					{
						::SetEvent(pSerialPort->hEventListenReadThread); //触发令牌获取回令
					}
				}
				//
				break;
			}
        case WAIT_OBJECT_0 + 1:  //结束
		{
			return 0;
			break;
		}
		default:
				break;
			
		}
		::ResetEvent(pSerialPort->hEventListenWriteThread);
	}
	return 0;
}

int CCOM::WriteBuffer(const unsigned char *buff, int buffsize, int &reqid)
{
	//m_Shibboleth
	if(nullptr == buff || 0 >= buffsize)
		return ERROR_PARAMS;

	::EnterCriticalSection(&m_csSync);
	reqid = (m_comPort & 0xFF )<< 24 | (++m_reqid & 0x00FFFFFF);
	m_Reqid.push_back(reqid);
	SComBuffer combuffer;
	combuffer.shibboleth.buff = buff;
	combuffer.shibboleth.buffsize = buffsize;
	combuffer.shibbolethRet = ERROR_NOEXECUTE;
	combuffer.backcrossRet = ERROR_NOEXECUTE;
	combuffer.backcross.buff = nullptr;
	combuffer.backcross.buffsize = 0;
	combuffer.backcross.timestamp = 0;
	m_SComBuffer.insert(std::make_pair<int,SComBuffer>(reqid,combuffer));
	::LeaveCriticalSection(&m_csSync);

	::SetEvent(hEventListenWriteThread);//触发写

	
	int ret = ERROR_DEFAULT;
	auto itr = m_SComBuffer.find(reqid);
	if(itr != m_SComBuffer.end())
	{
		long start = ::GetTickCount();
		long end = 0;
		while(true){ //等待发送完成通知
			ret = m_SComBuffer[reqid].shibbolethRet;
			if(ERROR_NOEXECUTE != ret) return ret; //未知值
			::Sleep(200);
			end = ::GetTickCount();
			if(end - start > timeout) break; //6秒超时
		}
	}
	return  ret;
}


bool CCOM::WriteComData(int reqid, const unsigned char* pData, unsigned int length)
{
	bool   bResult = TRUE;
	DWORD  BytesToSend = 0;
	auto &itr = m_SComBuffer.find(reqid);
	if(itr == m_SComBuffer.end())
	{
		return false;
	}

	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		itr->second.shibbolethRet = ERROR_INVALID_HANDLE_VALUE;
		return false;
	}
	printf("object[%X] reqid[%X] WRITE\n",this,reqid);
	for(int i=0;i<length;++i)
		printf("%02X",pData[i]);
	printf("\n");
	/** 向缓冲区写入指定量的数据 */
	bResult = (bool)WriteFile(m_hComm, pData, length, &BytesToSend, NULL);

	if (!bResult)
	{
		DWORD dwError = GetLastError();
		/** 清空串口缓冲区 */
		PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_RXABORT);
		m_SComBuffer[reqid].shibbolethRet = ERROR_READORWRITE;
		return false;
	}

	m_SComBuffer[reqid].shibbolethRet = BytesToSend;
	return true;
}


void CCOM::deleteReqidFront()
{
	::EnterCriticalSection(&m_csSync);
	if(!m_Reqid.empty())
		m_Reqid.pop_front();
	::LeaveCriticalSection(&m_csSync);
}

unsigned int CCOM::GetBytesInCOM()
{
	DWORD dwError = 0;  /** 错误码 */
	COMSTAT  comstat;   /** COMSTAT结构体,记录通信设备的状态信息 */
	memset(&comstat, 0, sizeof(COMSTAT));

	UINT BytesInQue = 0;
	/** 在调用ReadFile和WriteFile之前,通过本函数清除以前遗留的错误标志 */

	if (ClearCommError(m_hComm, &dwError, &comstat))
	{
		BytesInQue = comstat.cbInQue; /** 获取在输入缓冲区中的字节数 */
	}
	return BytesInQue;
}

bool CCOM::ReadComData(int reqid, unsigned char* pData, unsigned int length)
{
	bool  bResult = true;
	DWORD BytesRead = 0;
	auto itr = m_SComBuffer.find(reqid);
	if(itr == m_SComBuffer.end())
	{
		return false;
	}

	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		m_SComBuffer[reqid].backcrossRet = ERROR_INVALID_HANDLE_VALUE;
		return false;
	}

	/** 从缓冲区读取一个字节的数据 */
	bResult = (bool)ReadFile(m_hComm, pData, length, &BytesRead, NULL);
	printf("object[%X] reqid[%X] READ\n",this,reqid);
	for(int i=0;i<BytesRead;++i)
		printf("%02X",pData[i]);
	printf("\n");
	if ((!bResult))
	{

		/** 获取错误码,可以根据该错误码查出错误原因 */
		DWORD dwError = GetLastError();
		/** 清空串口缓冲区 */
		PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_RXABORT);
		m_SComBuffer[reqid].backcrossRet  = ERROR_READORWRITE;
		return false;

	}

	/** 离开临界区 */
	m_SComBuffer[reqid].backcrossRet =  BytesRead;
	return true;
}

int CCOM::ReadBufferLen(const int reqid)
{
	auto itr = m_SComBuffer.find(reqid);
	if(itr == m_SComBuffer.end())
	{
		return ERROR_PARAMS;
	}
	int ret = ERROR_DEFAULT;
	long start = ::GetTickCount();
	long end = 0;
	while(true){ //等待发送完成通知
		ret = m_SComBuffer[reqid].backcrossRet;
		if(ERROR_NOEXECUTE != ret) return ret; //未知值
		::Sleep(200);
		end = ::GetTickCount();
		if(end - start > timeout) break; //6秒超时
	}
	return ret;
}

int CCOM::ReadBuffer(const int reqid, unsigned char *buff, int buffsize)
{
	auto itr = m_SComBuffer.find(reqid);
	if(itr == m_SComBuffer.end())
	{
		return ERROR_PARAMS;
	}
	if(buffsize < itr->second.backcross.buffsize)
		return ERROR_PARAMS;
	int ret = ERROR_DEFAULT;
	memcpy(buff,itr->second.backcross.buff,itr->second.backcross.buffsize);
	ret = itr->second.backcross.buffsize;
	m_SComBuffer.erase(itr);//口令 回令 销毁
	return ret;
}



CComHelper* CComHelper::getInstance()
{
	static CComHelper comHelper;
	return &comHelper;
}


HANDLE CComHelper::CreatePort(UINT  portNo, UINT  baud, char  parity, UINT  databits, UINT  stopsbits)
{
	if(0 < m_mapPortCom.count(portNo))
		return m_mapPortCom[portNo]->GetComHandle();
	CCOM* com = new CCOM(portNo,baud,parity,databits,stopsbits);
	m_mapPortCom[portNo] = com;
	m_mapHandlePort[com->GetComHandle()] = portNo;
	return com->GetComHandle();
}

bool CComHelper::RemovePort(HANDLE h)
{
	if(0 >= m_mapHandlePort.count(h))
		return false;
	auto itr = m_mapPortCom.find(m_mapHandlePort[h]);
	if(m_mapPortCom.end() != itr)
		m_mapPortCom.erase(itr);

	return true;
}

int CComHelper::Write(HANDLE h,const unsigned char *buff, int buffsize, int &reqid)
{
	if(0 >= m_mapHandlePort.count(h))
		return -1;
	auto itr = m_mapPortCom.find(m_mapHandlePort[h]);
	if(m_mapPortCom.end() != itr)
		return itr->second->WriteBuffer(buff,buffsize,reqid);
	return -1;
}

int CComHelper::ReadLen(HANDLE h,const int reqid)
{
	if(0 >= m_mapHandlePort.count(h))
		return -1;
	auto itr = m_mapPortCom.find(m_mapHandlePort[h]);
	if(m_mapPortCom.end() != itr)
		return itr->second->ReadBufferLen(reqid);
	return -1;
}

int CComHelper::Read(HANDLE h,const int reqid, unsigned char *buff, int buffsize)
{
	if(0 >= m_mapHandlePort.count(h))
		return -1;
	auto itr = m_mapPortCom.find(m_mapHandlePort[h]);
	if(m_mapPortCom.end() != itr)
		return itr->second->ReadBuffer(reqid,buff,buffsize);
	return -1;
}

bool CComHelper::SetTimeout(HANDLE h,int time)
{
	if(0 >= m_mapHandlePort.count(h))
		return false;
	auto itr = m_mapPortCom.find(m_mapHandlePort[h]);
	if(m_mapPortCom.end() != itr)
		return itr->second->SetTimeout(time);
	return false;
}

使用案例:

获取端口数据长度和获取端口数据2个接口,内部实现了超时机制,上传只需阻塞式调用。

Windows下实现COM口通信c++源代码(验证可行)

 啥也不说了,一切都在代码里。如果有用记得一键三连。笔芯!!!

上一篇:winpe启动盘制作


下一篇:容器排序