a
This commit is contained in:
@@ -0,0 +1,425 @@
|
||||
# 通信工具
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [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)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
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的通信工具集成功了多种通信方式,为设备连接、固件升级和数据同步提供了可靠的基础。通过深入分析这些模块的实现机制,开发者可以更好地理解和使用这些工具,提高开发效率和系统稳定性。
|
||||
Reference in New Issue
Block a user