# 通信工具 **本文档引用的文件** - [SComPort.cpp](file://cpp\Tools\SComPort.cpp) - [SComPort.h](file://h\SComPort.h) - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp) - [TcpClient.h](file://h\TcpClient.h) - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp) - [Zmodem.h](file://h\Zmodem.h) - [FileTransfer.cpp](file://cpp\Tools\FileTransfer.cpp) - [FileTransfer.h](file://h\FileTransfer.h) - [FileTransfer_crul.cpp](file://cpp\Tools\FileTransfer_crul.cpp) - [FileTransfer_crul.h](file://h\FileTransfer_crul.h) - [HttpDownload.cpp](file://cpp\Tools\HttpDownload.cpp) - [HttpDownload.h](file://h\HttpDownload.h) - [Constant.h](file://h\Constant.h) - [CtrlProtocolDef.h](file://h\CtrlProtocolDef.h) ## 目录 1. [引言](#引言) 2. [串口通信模块](#串口通信模块) 3. [TCP通信模块](#tcp通信模块) 4. [Zmodem文件传输协议](#zmodem文件传输协议) 5. [文件传输协作机制](#文件传输协作机制) 6. [HTTP下载功能](#http下载功能) 7. [应用场景与调用示例](#应用场景与调用示例) 8. [最佳实践](#最佳实践) 9. [结论](#结论) ## 引言 GeomativeStudio中的通信工具集成了多种通信方式,包括串口通信、TCP通信、Zmodem协议文件传输和HTTP下载功能。这些工具为设备连接、固件升级和数据同步等关键功能提供了底层支持。本文档详细分析了这些通信模块的实现机制与使用方法。 ## 串口通信模块 ### SComPort类实现 `SComPort`类封装了Windows平台下的串口通信功能,提供了异步读写、超时控制和多线程安全处理等特性。 **串口初始化与配置** `SComPort`类通过`OpenComm`方法初始化串口连接,设置通信参数如波特率(115200)、数据位(8位)、奇偶校验(无)和停止位(1位)。该类使用重叠I/O(Overlapped I/O)实现异步通信,确保主线程不会被阻塞。 ```mermaid classDiagram class CSComPort { +CString m_szComName +HANDLE m_hCom +HWND m_hOwnerWnd +long m_lCommID +DCB m_dcbBlock +char m_aWriteBuffer[WRITEBUFFER_SIZE] +int m_iWriteSize +char m_aReadBuffer[READBUFFER_SIZE] +int m_iReadSize +DWORD m_dwBLThreadID +HANDLE m_hBLThread +BOOL m_bIsDetBreakFun +BOOL m_bIsScanBreak +DWORD m_dwFactdata +FILE* m_Log +CSComPort() +CSComPort(HWND hOwnerWnd, long lCommID) +~CSComPort() +BOOL FindComName(CStringArray* pStringArray) +BOOL OpenComm(CString szComName) +void SetOwnerWnd(HWND hOwnerWnd) +void SetCommID(long lCommID) +void CloseComm() +BOOL ReceiveDataDirectly(char* pDataBuff, int* iDataSize) +BOOL SendDataDirectly(char* pDataBuff, int iDataSize) +void SetScanBreakSign(BOOL bIsScanBreak) +void ClearCommSendBuff() +void ClearCommReceiveBuff() +BOOL ZmodemReceiveDataDirectly(char* pDataBuff, int* iDataSize) +BOOL ZmodemSendDataDirectly(char* pDataBuff, int iDataSize) +static UINT SComPortDetectBreakThreadFun(LPVOID pParam) } ``` **Diagram sources** - [SComPort.h](file://h\SComPort.h#L14-L73) - [SComPort.cpp](file://cpp\Tools\SComPort.cpp#L31-L285) **异步读写机制** `ReceiveDataDirectly`和`SendDataDirectly`方法实现了异步读写功能。读取操作首先通过`ClearCommError`检查输入缓冲区中的数据量,然后使用`ReadFile`函数进行异步读取。如果`ReadFile`立即返回`ERROR_IO_PENDING`,则通过`GetOverlappedResult`等待操作完成。 **超时控制** 通信超时通过`GetOverlappedResult`的最后一个参数`TRUE`实现,该参数指示函数应阻塞直到操作完成或超时。日志记录功能通过`fopen`打开日志文件"LOG\\commLog.txt"实现,所有发送和接收的数据都会被记录。 **多线程安全处理** `SComPort`类通过`m_hBLThread`线程监控串口连接状态。`SComPortDetectBreakThreadFun`线程函数定期尝试重新打开串口,如果失败则通过`SendMessage`通知所有者窗口串口已断开。 **Section sources** - [SComPort.cpp](file://cpp\Tools\SComPort.cpp#L306-L403) - [SComPort.cpp](file://cpp\Tools\SComPort.cpp#L527-L576) - [SComPort.cpp](file://cpp\Tools\SComPort.cpp#L225-L256) ## TCP通信模块 ### TcpClient类实现 `CTcpClient`类实现了TCP客户端通信功能,支持连接管理、数据收发和异常重连。 ```mermaid classDiagram class CTcpClient { +CString m_strIP +WORD m_wPort +SOCKET m_sockClient +int m_iRcvBuf +int m_iSndBuf +bool m_bIsConnect +char* m_pClearRcvBuf +CTcpClient() +~CTcpClient() +bool InitailTcp() +bool ConnectServer(CString strAddr, WORD wPort) +bool ConnectToServer(CString strIP, WORD wPort) +int SendData(const char* pData, int wLen) +bool CloseConnect() +bool GetConnectStatus() +bool ReConnect() +bool RecvData(char* pData, int iLen, int& iActualLen) +bool Disconnect() +bool ClearRecvBuffer() } ``` **Diagram sources** - [TcpClient.h](file://h\TcpClient.h#L18-L75) - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp#L26-L39) **连接管理** `InitailTcp`方法初始化套接字,设置套接字选项如`SO_LINGER`、接收/发送缓冲区大小和`SO_KEEPALIVE`。`ConnectServer`方法建立与服务器的连接,`CloseConnect`方法关闭连接并释放资源。 **数据收发** `SendData`方法使用`send`函数发送数据,`RecvData`方法使用`select`函数实现非阻塞接收。`select`函数检查套接字是否有数据可读,超时时间为25毫秒。 **异常重连** `ReConnect`方法实现了异常重连机制。当连接断开时,先调用`CloseConnect`关闭现有连接,然后重新初始化套接字并通过`ConnectToServer`重新连接。 **Section sources** - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp#L48-L97) - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp#L101-L130) - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp#L252-L278) ## Zmodem文件传输协议 ### Zmodem类实现 `Zmodem`类实现了Zmodem协议,用于在串口连接上进行可靠的文件传输。 ```mermaid classDiagram class Zmodem { +CSComPort* port +FILE* file +long file_length +long byte_count +int file_count +char file_name[128] +char buffer[BUFFSIZE] +unsigned long m_FileSize +int m_ByteTransfer +char m_WriteBuff[8192] +int m_WriteBuffLength +int m_nBufReadIndex +FILE* zmodemLog +DWORD dwBegin +char cReadLog[2048] +int nLogLength +int nIndex +Zmodem(CSComPort* rs232_port) +~Zmodem() +BOOL Send(char* files[]) +BOOL Receive(CString Path) +BOOL SendCancelString() +int GetTransferPosit() +int GetFileSize() } ``` **Diagram sources** - [Zmodem.h](file://h\Zmodem.h#L31-L142) - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp#L33-L56) **帧结构解析** Zmodem协议使用多种帧类型进行通信,包括`ZRQINIT`、`ZRINIT`、`ZFILE`、`ZDATA`、`ZEOF`和`ZFIN`。`ReadHeader`方法解析接收到的帧头,`SendBinaryHeader`方法发送二进制帧头。 **错误校验** Zmodem协议使用CRC-16或CRC-32进行错误校验。`Crc16`和`Crc32`类用于计算数据的校验和。`SendDataFrame`方法在发送数据帧时包含校验信息。 **断点续传机制** `ReceiveSingleFile`方法实现了断点续传功能。当接收文件时,如果文件已存在且大小与远程文件相同,则发送`ZRPOS`帧请求从上次中断的位置继续传输。 **Section sources** - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp#L128-L127) - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp#L558-L774) - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp#L253-L258) ## 文件传输协作机制 ### FileTransfer与FileTransfer_crul协作 `FileTransfer`和`FileTransfer_crul`类共同实现了设备与主机间的文件传输功能。 ```mermaid classDiagram class FileTransfer { +CSComPort* port +FILE* file +long file_length +long byte_count +int file_count +char file_name[128] +char buffer[BUFFSIZE] +FileTransfer() +virtual ~FileTransfer() +virtual void error(char* fmt, ...) +virtual void status(char* fmt, ...) +virtual BOOL Send(char* files[]) = 0 +virtual BOOL Receive(CString Path) = 0 } class FileTransfer_crul { +CURL* m_pCrEasyHandl +CURL* m_pCrPuteasyHandl +FILE* m_pLog +CString m_strUrl +CString m_strSavePath +CString m_strSaveName +bool m_bIsNeedProgress +bool m_bIsNeedErrInfo +int m_nTimeOut +bool m_bIsGobalInitial +bool m_bIsHttpsFlag +bool m_bIsSSLCertify +FileTransfer_crul() +virtual ~FileTransfer_crul() +bool Inital() +void UnInital() +void SetOption(EnOptFlag enFlag, CString strInfo, bool bFlag = false) +bool DownloadFile() +DOUBLE GetFileSize() +bool GetUrlResConValild() +void InitalLogInfo() +static size_t WriteToFile(void* ptr, size_t size, size_t nmemb, void* userp) +static int xferinfo(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +static size_t WriteToBuff(void* ptr, size_t size, size_t nmemb, void* userp) +static size_t WriteFuncForUrlTest(void* ptr, size_t size, size_t nmemb, void* userp) +void PrintLog(CString strLog) } FileTransfer <|-- Zmodem : "extends" FileTransfer_crul --> CURL : "uses" ``` **Diagram sources** - [FileTransfer.h](file://h\FileTransfer.h#L26-L48) - [FileTransfer_crul.h](file://h\FileTransfer_crul.h#L55-L110) - [FileTransfer_crul.cpp](file://cpp\Tools\FileTransfer_crul.cpp#L24-L62) **协作流程** `FileTransfer`作为基类定义了文件传输的接口,`Zmodem`类继承自`FileTransfer`并实现了基于串口的文件传输。`FileTransfer_crul`类使用libcurl库实现HTTP/HTTPS文件下载功能。 **Section sources** - [FileTransfer.cpp](file://cpp\Tools\FileTransfer.cpp#L28-L47) - [FileTransfer_crul.cpp](file://cpp\Tools\FileTransfer_crul.cpp#L151-L281) ## HTTP下载功能 ### HttpDownload类实现 `HttpDownload`类实现了HTTP协议下载功能,支持多线程下载和断点续传。 ```mermaid classDiagram class HttpDownload { +BOOL m_bSupportResume +BOOL m_bResume +BOOL m_bStop +BOOL m_bIsUseFile +BOOL m_bFileLocked +BOOL m_bAddSize +DWORD m_dwDownloadSize +int runningThreadCnt +int nComplete +CString m_strServer +CString m_strObject +CString m_strSavePath +CString m_strTempSavePath +CString m_strReferer +CString m_strDownloadUrl +CTime m_TimeLastModified +UINT m_nPort +FILE* globalFile +DWORD m_dwFileSize +int m_dwThreadCnt +InforImpl inforImpl +NewTask TaskInfo +CSocket m_pSocket +HttpDownload() +virtual ~HttpDownload() +void FreeMemory() +void SetStop(bool stop) +BOOL StartHttpTask(NewTask task) +bool CreateNewFile(CString fileName, DWORD size) +void GetInfofromDevision() +bool GetInfofromTemp(CString filename) +void CreateInforImpl(CString str) +UINT SendRequest(BOOL bHead = false) +UINT GetInfo(LPCTSTR lpszHeader, DWORD& dwContentLength, DWORD& dwStatusCode, CTime& TimeLastModified) +BOOL ParseURL(CString str) +CTime GetTime(LPCTSTR lpszTime) +bool WriteInfoToFile() +bool WriteToFile(CString filePath, DWORD pos, char* buffer, int len) +void CreateThread() +bool Download(int index) } class InforImpl { +CString server +CString object +CString savePath +DWORD fileSize +int threadCnt +DWORD downloadSize +FromToImpl* fromToImpl } class FromToImpl { +DWORD from +DWORD to } class NewTask { +CString server +CString object +UINT port +UINT threadCnt +CString savepath } HttpDownload --> InforImpl : "contains" HttpDownload --> FromToImpl : "contains" HttpDownload --> NewTask : "uses" ``` **Diagram sources** - [HttpDownload.h](file://h\HttpDownload.h#L69-L154) - [HttpDownload.cpp](file://cpp\Tools\HttpDownload.cpp#L26-L46) **多线程下载** `StartHttpTask`方法首先发送HTTP请求获取文件大小,然后根据文件大小和线程数分配下载任务。每个线程负责下载文件的一部分,通过`Range`头指定下载范围。 **断点续传** `GetInfofromTemp`方法从临时配置文件中读取已下载的文件信息,实现断点续传功能。如果文件大小发生变化,则重新开始下载。 **Section sources** - [HttpDownload.cpp](file://cpp\Tools\HttpDownload.cpp#L68-L219) - [HttpDownload.cpp](file://cpp\Tools\HttpDownload.cpp#L104-L209) ## 应用场景与调用示例 ### 设备连接 ```mermaid sequenceDiagram participant 应用程序 participant SComPort participant 串口硬件 应用程序->>SComPort : OpenComm("COM1") SComPort->>串口硬件 : CreateFile("\\\\.\\COM1") 串口硬件-->>SComPort : 返回句柄 SComPort->>SComPort : 设置DCB参数 SComPort-->>应用程序 : 返回TRUE ``` **Diagram sources** - [SComPort.cpp](file://cpp\Tools\SComPort.cpp#L127-L223) ### 固件升级 ```mermaid sequenceDiagram participant 应用程序 participant Zmodem participant SComPort 应用程序->>Zmodem : Send(["firmware.bin"]) Zmodem->>SComPort : SendDataDirectly(ZRQINIT帧) SComPort->>Zmodem : 接收响应 Zmodem->>Zmodem : 发送ZFILE帧 Zmodem->>SComPort : 发送数据帧 loop 数据传输 SComPort->>Zmodem : 接收数据帧 Zmodem->>SComPort : 发送ZACK确认 end Zmodem->>SComPort : 发送ZFIN帧 SComPort->>Zmodem : 接收ZFIN响应 Zmodem-->>应用程序 : 返回TRUE ``` **Diagram sources** - [Zmodem.cpp](file://cpp\Tools\Zmodem.cpp#L62-L127) ### 数据同步 ```mermaid sequenceDiagram participant 应用程序 participant TcpClient participant 服务器 应用程序->>TcpClient : ConnectToServer("192.168.1.100", 8080) TcpClient->>服务器 : 建立TCP连接 服务器-->>TcpClient : 连接成功 TcpClient-->>应用程序 : 返回TRUE 应用程序->>TcpClient : SendData(同步数据) TcpClient->>服务器 : 发送数据 服务器-->>TcpClient : 返回响应 TcpClient-->>应用程序 : 返回发送字节数 ``` **Diagram sources** - [TcpClient.cpp](file://cpp\Tools\TcpClient.cpp#L101-L130) ## 最佳实践 ### 线程同步 使用Windows API的同步机制,如`CreateThread`和`WaitForSingleObject`,确保多线程环境下的数据一致性。 ### 资源释放 在析构函数中释放所有分配的资源,如关闭文件句柄、套接字和线程句柄。 ### 异常处理 使用`try-catch`块捕获异常,并通过日志记录详细的错误信息。 ## 结论 GeomativeStudio的通信工具集成功了多种通信方式,为设备连接、固件升级和数据同步提供了可靠的基础。通过深入分析这些模块的实现机制,开发者可以更好地理解和使用这些工具,提高开发效率和系统稳定性。