Selaa lähdekoodia

1、粘包、拆包

Jeff 5 vuotta sitten
vanhempi
commit
489ef2d745

+ 39 - 0
VideoCapture/VideoCapture/Device.cpp

@@ -0,0 +1,39 @@
+#include "StdAfx.h"
+#include "Device.h"
+#include "Device.h"
+
+std::map<int, CDevice> g_dmap;
+CDevice::CDevice()
+{
+}
+
+CDevice::~CDevice()
+{
+}
+
+bool CDevice::Open()
+{
+	return m_obj.OpenSerialPort(m_iPort, m_iBaudrate, m_iDatabit, m_iParitybit, m_iStopbit, 0, 0);
+}
+
+void CDevice::Close()
+{
+	m_obj.CloseSerialPort();
+}
+
+std::string CDevice::SendCommond(std::string cmd)
+{
+	if ( !m_obj.IsOpen() )
+		return std::string("串口未打开成功");
+
+	DWORD dwRet = m_obj.WriteComm((byte*)cmd.data(), cmd.size());
+	if ( dwRet != cmd.size() )
+		return std::string("写串口失败");
+
+	byte szData[1024 * 4] = {0};
+	dwRet = m_obj.ReadComm(szData, 1024 * 4);
+	if (dwRet == 0 )
+		return std::string("读串口失败");
+
+	return std::string((char*)szData, dwRet);
+}

+ 40 - 0
VideoCapture/VideoCapture/Device.h

@@ -0,0 +1,40 @@
+#ifndef __DEVICE_HEADER__
+#define __DEVICE_HEADER__
+
+#include "SynSerial.h"
+
+#pragma once
+class CDevice
+{
+	CSynSerial m_obj;
+public:
+	CDevice();
+	~CDevice();
+
+	bool Open();
+	void Close();
+	std::string SendCommond(std::string cmd);
+public:
+	int m_iID;						// -- 设备的ID
+	int m_iPort;					// -- 设备串口号
+	std::string m_strDeviceName;	// -- 设备名称
+	int m_iDeviceType;				// -- 设备类型
+	int m_iBaudrate;				// -- 波特率
+	int m_iDatabit;					// -- 数据位
+	int m_iStopbit;					// -- 停止位
+	int m_iParitybit;				// -- 奇偶校验位
+	int m_iRsmode;					// -- 串口通信方式,0 - RS232;1 - RS422; 2 - RS485
+	//////////////////////////////////////////////////////////////////////////
+	std::string m_strIp;			// -- ip地址号
+	int m_iIpport;					// -- ip端口号
+	int m_iCommmode;				// -- 通信的方式,有 0 - 串口方式;1 - tcp/ip...
+	int m_iDevideaddr;				// -- 设备地址
+	int m_iTimeout;					// -- 通讯超时
+	int m_iIsuse; 					// -- 是否启用设备1:启用,0:禁用
+	std::string m_strProtocoldllname;	// -- 协议DLL名称
+	int m_bySpecialdevice;			// -- Modbus Rtu;Modbus Ascii;Modbus Tcp;Snmp;RS232;
+};
+
+extern std::map<int, CDevice> g_dmap;
+
+#endif

+ 130 - 4
VideoCapture/VideoCapture/IOCPModel.cpp

@@ -114,11 +114,8 @@ DWORD WINAPI CIOCPModel::_WorkerThread(LPVOID lpParam)
 					 // Accept  
 				case ACCEPT_POSTED:
 					{ 
-
 						// 为了增加代码可读性,这里用专门的_DoAccept函数进行处理连入请求
-						pIOCPModel->_DoAccpet( pSocketContext, pIoContext );						
-						
-
+						pIOCPModel->_DoAccpet( pSocketContext, pIoContext );		
 					}
 					break;
 
@@ -500,6 +497,7 @@ bool CIOCPModel::_DoAccpet( PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT*
 	this->m_lpfnGetAcceptExSockAddrs(pIoContext->m_wsaBuf.buf, pIoContext->m_wsaBuf.len - ((sizeof(SOCKADDR_IN)+16)*2),  
 		sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, (LPSOCKADDR*)&LocalAddr, &localLen, (LPSOCKADDR*)&ClientAddr, &remoteLen);  
 
+	_RecvProcess(pSocketContext, pIoContext);
 	this->_ShowMessage( _T("客户端 %s:%d 连入."), inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port) );
 	//this->_ShowMessage( _T("客户额 %s:%d 信息:%s."),inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port),pIoContext->m_wsaBuf.buf );
 	//if ( Global::g_bEnableLog )
@@ -597,6 +595,7 @@ bool CIOCPModel::_DoRecv( PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT* pI
 	SOCKADDR_IN* ClientAddr = &pSocketContext->m_ClientAddr;
 	//this->_ShowMessage( _T("收到  %s:%d 信息:%s"),inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port), pIoContext->m_wsaBuf.buf );
 	
+	_RecvProcess(pSocketContext, pIoContext);
 	//if ( Global::g_bEnableLog )
 	//{
 	//	// 解析Json字符串;
@@ -767,6 +766,133 @@ void CIOCPModel::_ShowMessage(const CString szFormat,...) const
 #endif
 }
 
+#define PAK_LEN sizeof(_PACKAGE_)
+void CIOCPModel::_RecvProcess(PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT* pIoContext)
+{
+	int plen = sizeof(_PACKAGE_);
+	// 小于包头;
+	ProHeader* phead = NULL;
+	if (pSocketContext->lastData.size() == 0)
+	{
+		phead = (ProHeader*)pIoContext->m_wsaBuf.buf;
+
+		// 完成的包;
+		if (phead->len == pIoContext->m_wsaBuf.len)
+		{
+			_DeviceProc(pSocketContext, (Package*)pIoContext->m_wsaBuf.buf);
+		}
+		// 小包;
+		else if (phead->len < pIoContext->m_wsaBuf.len)
+		{
+			pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf, pIoContext->m_wsaBuf.len);
+		}
+		// 超包;
+		else if (phead->len > pIoContext->m_wsaBuf.len)
+		{
+			_DeviceProc(pSocketContext, (Package*)pIoContext->m_wsaBuf.buf);
+			pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf + phead->len, pIoContext->m_wsaBuf.len - phead->len);
+		}
+	}
+	else
+	{
+		int lastlen = pIoContext->m_wsaBuf.len;
+		if (pSocketContext->lastData.size() >= PAK_LEN)
+		{
+			phead = (ProHeader*)pSocketContext->lastData.data();
+			if (phead->len <= pSocketContext->lastData.size() + pIoContext->m_wsaBuf.len)
+			{
+				lastlen = pSocketContext->lastData.size() + pIoContext->m_wsaBuf.len - phead->len;
+				pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf, lastlen);
+				// 完整包;
+				_DeviceProc(pSocketContext, (Package*)pSocketContext->lastData.data());
+				// 剩余包;
+				pSocketContext->lastData.clear();
+				if (pIoContext->m_wsaBuf.len > lastlen)
+					pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf + lastlen, pIoContext->m_wsaBuf.len - lastlen);
+			}
+			else
+			{
+				pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf, pIoContext->m_wsaBuf.len);
+			}
+		}
+		else
+		{
+			int diflen = PAK_LEN - pSocketContext->lastData.size();
+			if ( diflen > pIoContext->m_wsaBuf.len )
+			{
+				pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf, pIoContext->m_wsaBuf.len);
+			}
+			else
+			{
+				pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf, diflen);
+				phead = (ProHeader*)pSocketContext->lastData.data();
+				// 完整包;
+				if ( phead->len == PAK_LEN + pIoContext->m_wsaBuf.len - diflen )
+				{
+					_DeviceProc(pSocketContext, (Package*)pIoContext->m_wsaBuf.buf);
+				}
+				// 小包;
+				else if ( phead->len > PAK_LEN + pIoContext->m_wsaBuf.len - diflen)
+				{
+					pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf + diflen, pIoContext->m_wsaBuf.len - diflen);
+				}
+				// 超包;
+				else if (phead->len < PAK_LEN + pIoContext->m_wsaBuf.len - diflen)
+				{
+					// 组完成包;
+					pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf + diflen, phead->len - PAK_LEN);
+					_DeviceProc(pSocketContext, (Package*)pIoContext->m_wsaBuf.buf);
+					pSocketContext->lastData.clear();
+					int last = pIoContext->m_wsaBuf.len - diflen - phead->len + PAK_LEN;
+					if (last)
+					{						
+						pSocketContext->lastData.append(pIoContext->m_wsaBuf.buf + pIoContext->m_wsaBuf.len - last, last);
+					}
+				}
+			}
+		}
+	}
+}
+
+void CIOCPModel::_DeviceProc(PER_SOCKET_CONTEXT* pSocketContext, Package* pak)
+{
+	if ( pak->header.version != 0xAA )
+	{
+		return;
+	}
+
+	cJSON* pJson = cJSON_Parse((const char*)pak->buf);
+	if ( pJson == NULL )
+	{
+		return;
+	}
+
+	RequesJson reqj;
+	reqj.device_id = cJSON_GetObjectItem(pJson, "device_id") ? cJSON_GetObjectItem(pJson, "device_id")->valueint : 0;
+	reqj.device_name = cJSON_GetObjectItem(pJson, "device_name") ? cJSON_GetObjectItem(pJson, "device_name")->valuestring : "";
+	reqj.device_cmd = cJSON_GetObjectItem(pJson, "device_cmd") ? cJSON_GetObjectItem(pJson, "device_cmd")->valuestring : "";
+
+	if ( pJson )
+	{
+		cJSON_Delete(pJson);
+		pJson = NULL;
+	}
+
+	auto iter = g_dmap.find(reqj.device_id);
+	if ( iter == g_dmap.end())
+	{
+		return;
+	}
+
+	auto value = iter->second;
+	std::string readdata = value.SendCommond(reqj.device_cmd);
+
+	ResponseJson repj;
+	repj.device_id = reqj.device_id;
+	repj.device_name = reqj.device_name;
+	repj.device_result_des = readdata;
+}
+
 /////////////////////////////////////////////////////////////////////
 // 判断客户端Socket是否已经断开,否则在一个无效的Socket上投递WSARecv操作会出现异常
 // 使用的方法是尝试向这个socket发送数据,判断这个socket调用的返回值

+ 31 - 0
VideoCapture/VideoCapture/IOCPModel.h

@@ -15,6 +15,34 @@
 // 默认IP地址
 #define DEFAULT_IP            _T("127.0.0.1")
 
+typedef struct _PRO_HEADER_
+{
+	byte	version;
+	unsigned int len; // header长度+buf长度;
+}ProHeader;
+
+// 请求包
+typedef struct _PACKAGE_
+{
+	ProHeader header;
+	byte	*buf; // json格式;
+}Package;
+
+typedef struct _REQUEST_JSON_
+{
+	int			device_id;
+	std::string		device_name;
+	std::string device_cmd;
+}RequesJson;
+
+typedef struct _RESPONSE_JSON_
+{
+	int			device_id;
+	std::string		device_name;
+	bool		device_cmd_result;	// 命令执行结果;
+	std::string device_result_des;	// 结果描述;
+}ResponseJson;
+
 
 //////////////////////////////////////////////////////////////////
 // 在完成端口上投递的I/O操作的类型
@@ -81,6 +109,7 @@ typedef struct _PER_SOCKET_CONTEXT
 	SOCKADDR_IN m_ClientAddr;                              // 客户端的地址
 	CArray<_PER_IO_CONTEXT*> m_arrayIoContext;             // 客户端网络操作的上下文数据,
 	                                                       // 也就是说对于每一个客户端Socket,是可以在上面同时投递多个IO请求的
+	std::string lastData;
 
 	// 初始化
 	_PER_SOCKET_CONTEXT()
@@ -232,6 +261,8 @@ protected:
 	// 在主界面中显示信息
 	void _ShowMessage( const CString szFormat,...) const;
 
+	void _RecvProcess(PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT* pIoContext);
+	void _DeviceProc(PER_SOCKET_CONTEXT* pSocketContext, Package *pak);
 private:
 
 	HANDLE                       m_hShutdownEvent;              // 用来通知线程系统退出的事件,为了能够更好的退出线程

+ 305 - 0
VideoCapture/VideoCapture/SynSerial.cpp

@@ -0,0 +1,305 @@
+#include "StdAfx.h"
+#include "SynSerial.h"
+
+CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
+, m_dwInQueue(1024)
+, m_dwOutQueue(1024)
+{
+	memset(&m_dcb, 0, sizeof(DCB));
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
+}
+
+CSynSerial::~CSynSerial(void)
+{
+	CloseSerialPort();
+}
+
+BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwBaudRate, IN CONST BYTE & bySize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST INT & nInterval)
+{
+	ASSERT(byCommPort);
+	CloseSerialPort();
+
+	_stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = bySize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 5000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+BOOL CSynSerial::ReOpenSerialPort()
+{
+	ASSERT(_tcslen(m_szSerialPort));
+	CloseSerialPort();
+
+	m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
+	if (m_hSerialPort == INVALID_HANDLE_VALUE)
+	{
+		// 打开串口失败;
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	BOOL bResult = FALSE;
+	// SetupComm设置缓冲区大小;
+	bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 在串口读写之前,清除缓冲区;
+	bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::CloseSerialPort()
+{
+	if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
+		CloseHandle(m_hSerialPort);
+	m_hSerialPort = NULL;
+}
+
+BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
+{
+	if (!IsOpen())
+		return FALSE;
+
+	BOOL bResult = FALSE;
+	// GetCommState获取设备控制块状态;
+	memset(&m_dcb, 0, sizeof(DCB));
+	bResult = GetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	m_dcb.Parity = byParity;
+	if (m_dcb.Parity == NOPARITY)
+		m_dcb.fParity = FALSE;
+	else
+		m_dcb.fParity = TRUE;
+
+	m_dcb.BaudRate = dwBaudRate;
+	m_dcb.ByteSize = byByteSize;
+	m_dcb.StopBits = byStopBits;
+	if (m_dcb.ByteSize == 8)
+		m_dcb.StopBits = ONESTOPBIT;
+
+	// SetCommState设置设备的控制块状态;
+	memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
+	bResult = SetCommState(m_hSerialPort, &m_dcb);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 获取设备的超时值;
+	bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	// 两字符之间最大的延时,设置0表示参数不起作用;
+	m_cts.ReadIntervalTimeout = 50;
+	m_cts.ReadTotalTimeoutMultiplier = 100;
+	m_cts.ReadTotalTimeoutConstant = 8000;
+	m_cts.WriteTotalTimeoutMultiplier = 100;
+	m_cts.WriteTotalTimeoutConstant = 3000;
+
+	// 设置设备的超时值;
+	bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
+	if (!bResult)
+	{
+		DWORD dwError = GetLastError();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
+{
+}
+
+void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
+{
+}
+
+DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
+{
+	if (!IsOpen())
+		return 0;
+
+	if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
+	{
+		return 0;
+	}
+	
+	DWORD dwErrorFlags;
+	DWORD dwBytesWritten = 0;	// 实际写入的字节数;
+	// 写前, 清除错误;
+	COMSTAT ComStat;
+	ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);	
+	// 写前,清空缓存区;
+	PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
+	if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, NULL) )
+	{
+		DWORD dwError = GetLastError();
+	}	
+
+	// 返回写入字节数;
+	return dwBytesWritten;
+}
+
+DWORD CSynSerial::ReadComm(IN BYTE * pReadBuf, IN CONST DWORD & dwReadSize)
+{
+	if (!IsOpen())
+		return 0;
+
+	if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
+	{
+		return 0;
+	}
+
+	DWORD dwBytesRead = 0;
+	DWORD dwErrorFlags = 0;
+	// ReadFile前,使用ClearCommError清除错误;
+	COMSTAT ComStat = {0};
+	DWORD dwLastLen = 0;
+	ULONGLONG ulTick = GetTickCount64();	
+	// 直到有数据为止,超时3秒;
+	while (true)
+	{// cbInQue表示输入缓冲区的字节数; 
+		Sleep(150);
+		if (GetTickCount64() - ulTick > 3000)
+			break;
+		ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
+		// 防止读一次没读完,再读一次;二次长度一样表示读完;
+		if (ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue)
+			break;
+		dwLastLen = ComStat.cbInQue;
+	}
+
+	if (ComStat.cbInQue == 0)
+	{
+		// 串口超时,无数据返回;
+		return 0;
+	}
+
+	dwBytesRead = ComStat.cbInQue;
+	if (dwReadSize < dwBytesRead)
+	{
+		dwBytesRead = dwReadSize;
+	}
+
+	if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
+	{
+		return (INT)dwBytesRead;
+	}
+
+	return dwBytesRead;
+}

+ 83 - 0
VideoCapture/VideoCapture/SynSerial.h

@@ -0,0 +1,83 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Home], 保留所有权利;
+/*  模 块 名:同步串口模块;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[Home];
+/*  日    期:[12/20/2017];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Home];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __SYN_SERIAL__
+#define __SYN_SERIAL__
+
+#pragma once
+
+#define MAX_PORT_LEN 10
+
+class CSynSerial
+{
+public:
+	CSynSerial(void);
+	virtual ~CSynSerial(void);
+
+private:
+	DCB		m_dcb;
+	HANDLE	m_hSerialPort;
+	COMMTIMEOUTS	m_cts;
+
+	// 串口号(1~255);
+	TCHAR	m_szSerialPort[MAX_PORT_LEN];
+	// 输入缓存大小(byte);
+	DWORD	m_dwInQueue;
+	// 输出缓存大小(byte);
+	DWORD	m_dwOutQueue;
+
+public:
+	inline BOOL IsOpen() const {
+		return (m_hSerialPort == NULL || m_hSerialPort == INVALID_HANDLE_VALUE) ? FALSE : TRUE;
+	}
+
+	// 打开串口;
+	BOOL OpenSerialPort(
+		IN CONST BYTE& byCommPort,		// 串口号;
+		IN CONST DWORD& dwBaudRate,		// 波特率;
+		IN CONST BYTE& bySize,			// 数据位;
+		IN CONST BYTE& byParity,		// 校验位;
+		IN CONST BYTE& byStopBits,		// 停止位;
+		IN CONST BYTE& byStartAddr,		// 起始地址;
+		IN CONST INT& nInterval			// 间隔时间;
+	);
+	// 重装打开串口;
+	BOOL ReOpenSerialPort();
+	// 关闭串口;
+	void CloseSerialPort();
+	// 设置串口参数;
+	BOOL SetSerialPort(
+		IN CONST DWORD& dwBaudRate,		// 波特率;
+		IN CONST BYTE& byByteSize,		// 数据位;
+		IN CONST BYTE& byParity,		// 校验位;
+		IN CONST BYTE& byStopBits,		// 停止位;
+		IN CONST BYTE& byStartAddr,		// 起始地址;
+		IN CONST DWORD& dwInQueue,		// 输入缓存;
+		IN CONST DWORD& dwOutQueue		// 输出缓存;
+		);
+
+	// 设置dcb参数;
+	void SetSerialDCB(IN CONST DCB &dcb);
+	// 设置commtimeouts参数;
+	void SetSerialCommTimeouts(IN CONST COMMTIMEOUTS &commTimeouts);
+
+	virtual DWORD WriteComm(IN BYTE *pWirteBuf, IN CONST INT32 nWriteSize);
+	virtual DWORD ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& nReadSize);
+};
+
+#endif // __SYN_SERIAL__

+ 19 - 1
VideoCapture/VideoCapture/VideoCapture.cpp

@@ -22,6 +22,8 @@
 #include "VideoCaptureDoc.h"
 #include "VideoCaptureView.h"
 
+#include "IOCPModel.h"
+
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #endif
@@ -108,9 +110,25 @@ BOOL CVideoCaptureApp::InitInstance()
 #endif
 
 	Global::GetConfig();
-
 	Global::WriteTextLog("程序启动");
 
+	CDevice dev;
+	dev.m_iBaudrate = 115200;
+	dev.m_iDatabit = 8;
+	dev.m_iPort = 3;
+	dev.m_iParitybit = 0;
+	dev.m_iStopbit = 1;
+	dev.m_iID = 1;
+	dev.m_strDeviceName = "Chroma22293";
+	dev.m_iDeviceType = 1;
+	dev.Open();
+
+	g_dmap.insert(std::pair<int, CDevice>(dev.m_iID,dev));
+
+	CIOCPModel iocp;
+	iocp.LoadSocketLib();
+	iocp.Start(5566);
+
 	// 初始化 OLE 库
 	if (!AfxOleInit())
 	{

+ 4 - 0
VideoCapture/VideoCapture/VideoCapture.vcxproj

@@ -154,6 +154,7 @@ copy "$(SolutionDir)AMESDK.DLL" "$(TargetDir)AMESDK.dll" /y/a</Command>
     <ClInclude Include="calendarbar.h" />
     <ClInclude Include="ClassView.h" />
     <ClInclude Include="CritSection.h" />
+    <ClInclude Include="Device.h" />
     <ClInclude Include="DlgIRControl.h" />
     <ClInclude Include="FileView.h" />
     <ClInclude Include="framework.h" />
@@ -171,6 +172,7 @@ copy "$(SolutionDir)AMESDK.DLL" "$(TargetDir)AMESDK.dll" /y/a</Command>
     <ClInclude Include="SpreadSheet.h" />
     <ClInclude Include="stdafx.h" />
     <ClInclude Include="stdint.h" />
+    <ClInclude Include="SynSerial.h" />
     <ClInclude Include="targetver.h" />
     <ClInclude Include="tinyxml2.h" />
     <ClInclude Include="TrayIcon.h" />
@@ -196,6 +198,7 @@ copy "$(SolutionDir)AMESDK.DLL" "$(TargetDir)AMESDK.dll" /y/a</Command>
     <ClCompile Include="..\UI\XColorStatic.cpp" />
     <ClCompile Include="calendarbar.cpp" />
     <ClCompile Include="ClassView.cpp" />
+    <ClCompile Include="Device.cpp" />
     <ClCompile Include="DlgIRControl.cpp" />
     <ClCompile Include="FileView.cpp" />
     <ClCompile Include="Global.cpp" />
@@ -211,6 +214,7 @@ copy "$(SolutionDir)AMESDK.DLL" "$(TargetDir)AMESDK.dll" /y/a</Command>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="SynSerial.cpp" />
     <ClCompile Include="tinyxml2.cpp">
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>

+ 12 - 0
VideoCapture/VideoCapture/VideoCapture.vcxproj.filters

@@ -144,6 +144,12 @@
     <ClInclude Include="..\cJson\cJSON.h">
       <Filter>json</Filter>
     </ClInclude>
+    <ClInclude Include="Device.h">
+      <Filter>iocp</Filter>
+    </ClInclude>
+    <ClInclude Include="SynSerial.h">
+      <Filter>iocp</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="VideoCapture.cpp">
@@ -239,6 +245,12 @@
     <ClCompile Include="..\cJson\cJSON.c">
       <Filter>json</Filter>
     </ClCompile>
+    <ClCompile Include="Device.cpp">
+      <Filter>iocp</Filter>
+    </ClCompile>
+    <ClCompile Include="SynSerial.cpp">
+      <Filter>iocp</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="VideoCapture.rc">

+ 3 - 2
VideoCapture/VideoCapture/stdafx.h

@@ -48,10 +48,11 @@ using namespace chrono;
 #define DEFAULT_PRODUCT_VERSION				""
 // END
 //////////////////////////////////////////////////////////////////////////
-
+#include <string>
+#include <map>
 #include "Global.h"
 #include <afxcontrolbars.h>
 #include "tinyxml2.h"
 #include "cJSON.h"
-
+#include "Device.h"
 #endif //PCH_H