14 KiB
通信工具
**本文档引用的文件** - [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)目录
引言
GeomativeStudio中的通信工具集成了多种通信方式,包括串口通信、TCP通信、Zmodem协议文件传输和HTTP下载功能。这些工具为设备连接、固件升级和数据同步等关键功能提供了底层支持。本文档详细分析了这些通信模块的实现机制与使用方法。
串口通信模块
SComPort类实现
SComPort类封装了Windows平台下的串口通信功能,提供了异步读写、超时控制和多线程安全处理等特性。
串口初始化与配置
SComPort类通过OpenComm方法初始化串口连接,设置通信参数如波特率(115200)、数据位(8位)、奇偶校验(无)和停止位(1位)。该类使用重叠I/O(Overlapped I/O)实现异步通信,确保主线程不会被阻塞。
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
- SComPort.cpp
异步读写机制
ReceiveDataDirectly和SendDataDirectly方法实现了异步读写功能。读取操作首先通过ClearCommError检查输入缓冲区中的数据量,然后使用ReadFile函数进行异步读取。如果ReadFile立即返回ERROR_IO_PENDING,则通过GetOverlappedResult等待操作完成。
超时控制
通信超时通过GetOverlappedResult的最后一个参数TRUE实现,该参数指示函数应阻塞直到操作完成或超时。日志记录功能通过fopen打开日志文件"LOG\commLog.txt"实现,所有发送和接收的数据都会被记录。
多线程安全处理
SComPort类通过m_hBLThread线程监控串口连接状态。SComPortDetectBreakThreadFun线程函数定期尝试重新打开串口,如果失败则通过SendMessage通知所有者窗口串口已断开。
Section sources
- SComPort.cpp
- SComPort.cpp
- SComPort.cpp
TCP通信模块
TcpClient类实现
CTcpClient类实现了TCP客户端通信功能,支持连接管理、数据收发和异常重连。
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
- TcpClient.cpp
连接管理
InitailTcp方法初始化套接字,设置套接字选项如SO_LINGER、接收/发送缓冲区大小和SO_KEEPALIVE。ConnectServer方法建立与服务器的连接,CloseConnect方法关闭连接并释放资源。
数据收发
SendData方法使用send函数发送数据,RecvData方法使用select函数实现非阻塞接收。select函数检查套接字是否有数据可读,超时时间为25毫秒。
异常重连
ReConnect方法实现了异常重连机制。当连接断开时,先调用CloseConnect关闭现有连接,然后重新初始化套接字并通过ConnectToServer重新连接。
Section sources
- TcpClient.cpp
- TcpClient.cpp
- TcpClient.cpp
Zmodem文件传输协议
Zmodem类实现
Zmodem类实现了Zmodem协议,用于在串口连接上进行可靠的文件传输。
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
- Zmodem.cpp
帧结构解析
Zmodem协议使用多种帧类型进行通信,包括ZRQINIT、ZRINIT、ZFILE、ZDATA、ZEOF和ZFIN。ReadHeader方法解析接收到的帧头,SendBinaryHeader方法发送二进制帧头。
错误校验
Zmodem协议使用CRC-16或CRC-32进行错误校验。Crc16和Crc32类用于计算数据的校验和。SendDataFrame方法在发送数据帧时包含校验信息。
断点续传机制
ReceiveSingleFile方法实现了断点续传功能。当接收文件时,如果文件已存在且大小与远程文件相同,则发送ZRPOS帧请求从上次中断的位置继续传输。
Section sources
- Zmodem.cpp
- Zmodem.cpp
- Zmodem.cpp
文件传输协作机制
FileTransfer与FileTransfer_crul协作
FileTransfer和FileTransfer_crul类共同实现了设备与主机间的文件传输功能。
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
- FileTransfer_crul.h
- FileTransfer_crul.cpp
协作流程
FileTransfer作为基类定义了文件传输的接口,Zmodem类继承自FileTransfer并实现了基于串口的文件传输。FileTransfer_crul类使用libcurl库实现HTTP/HTTPS文件下载功能。
Section sources
- FileTransfer.cpp
- FileTransfer_crul.cpp
HTTP下载功能
HttpDownload类实现
HttpDownload类实现了HTTP协议下载功能,支持多线程下载和断点续传。
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
- HttpDownload.cpp
多线程下载
StartHttpTask方法首先发送HTTP请求获取文件大小,然后根据文件大小和线程数分配下载任务。每个线程负责下载文件的一部分,通过Range头指定下载范围。
断点续传
GetInfofromTemp方法从临时配置文件中读取已下载的文件信息,实现断点续传功能。如果文件大小发生变化,则重新开始下载。
Section sources
- HttpDownload.cpp
- HttpDownload.cpp
应用场景与调用示例
设备连接
sequenceDiagram
participant 应用程序
participant SComPort
participant 串口硬件
应用程序->>SComPort : OpenComm("COM1")
SComPort->>串口硬件 : CreateFile("\\\\.\\COM1")
串口硬件-->>SComPort : 返回句柄
SComPort->>SComPort : 设置DCB参数
SComPort-->>应用程序 : 返回TRUE
Diagram sources
- SComPort.cpp
固件升级
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
数据同步
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
最佳实践
线程同步
使用Windows API的同步机制,如CreateThread和WaitForSingleObject,确保多线程环境下的数据一致性。
资源释放
在析构函数中释放所有分配的资源,如关闭文件句柄、套接字和线程句柄。
异常处理
使用try-catch块捕获异常,并通过日志记录详细的错误信息。
结论
GeomativeStudio的通信工具集成功了多种通信方式,为设备连接、固件升级和数据同步提供了可靠的基础。通过深入分析这些模块的实现机制,开发者可以更好地理解和使用这些工具,提高开发效率和系统稳定性。