Files
T
coco df489d5640 a
2026-07-03 16:05:30 +08:00

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)

目录

  1. 引言
  2. 串口通信模块
  3. TCP通信模块
  4. Zmodem文件传输协议
  5. 文件传输协作机制
  6. HTTP下载功能
  7. 应用场景与调用示例
  8. 最佳实践
  9. 结论

引言

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

异步读写机制 ReceiveDataDirectlySendDataDirectly方法实现了异步读写功能。读取操作首先通过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_KEEPALIVEConnectServer方法建立与服务器的连接,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协议使用多种帧类型进行通信,包括ZRQINITZRINITZFILEZDATAZEOFZFINReadHeader方法解析接收到的帧头,SendBinaryHeader方法发送二进制帧头。

错误校验 Zmodem协议使用CRC-16或CRC-32进行错误校验。Crc16Crc32类用于计算数据的校验和。SendDataFrame方法在发送数据帧时包含校验信息。

断点续传机制 ReceiveSingleFile方法实现了断点续传功能。当接收文件时,如果文件已存在且大小与远程文件相同,则发送ZRPOS帧请求从上次中断的位置继续传输。

Section sources

  • Zmodem.cpp
  • Zmodem.cpp
  • Zmodem.cpp

文件传输协作机制

FileTransfer与FileTransfer_crul协作

FileTransferFileTransfer_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的同步机制,如CreateThreadWaitForSingleObject,确保多线程环境下的数据一致性。

资源释放

在析构函数中释放所有分配的资源,如关闭文件句柄、套接字和线程句柄。

异常处理

使用try-catch块捕获异常,并通过日志记录详细的错误信息。

结论

GeomativeStudio的通信工具集成功了多种通信方式,为设备连接、固件升级和数据同步提供了可靠的基础。通过深入分析这些模块的实现机制,开发者可以更好地理解和使用这些工具,提高开发效率和系统稳定性。