www.pudn.com > 通信接口类.rar > CommInterface.h


/************************************************************************************ 
 * 文件名: CommInterface.h 
 * 版权: Copyright (C) DavidHowe 
 * 作者: 郝智龙 David Howe 
 * E-mail: davidhowe@sina.com 
 * Mobile Phone: *********** 
 * 创建时间: 2003-4-23 10:44:41 AM;  地点: Xi'an 
 * 文件说明: 创建这个类, 使得各种常用通信方式在使用时达到统一. 
 * 修改记录: -------------- +: 新增  o: 修改  -: 删除 -------------- 
       2003-4-23: + 创建文件. 
	   2003-4-30: + 基本完成了串口方式的代码(m_nCommMode=0). 
	   2003-5-2:  + 基本完成了TCP方式的代码(m_nCommMode=1,2). 
       2003-6-?:  o 增加了对WSAEISCONN的判断. 
       2003-7-?:  o 修正了发数线程启动时间过迟的bug. 
       2003-11-20: o 修正了一个可能会使命令堆积的bug. 
                    加入E1通信方式代码(m_nCommMode=3) 
       2004-3-31: 修改了事件m_hEvtCanGetCmdToSend的创建方式, 改为自动Reset. 
                  并在几个地方删掉了不必要的ResetEvent() 
       2004-4-2:  修改了判断TCP/IP方式下发送数据失败的代码. 
       2004-6-21: 使用OnSend()来判断是否能够继续发送数据. 
       2004-8-11: 
                   添加对::PostThreadMessage()的返回判断处理, 以修正在Dll工程中 
                   使用CCommInterface时不能启动发送数据线程的bug. 
                   {F598F388-14D8-464F-BE35-2CA67E1A978C} 
       2004-8-12: 添加宏判断, 使可以屏蔽E1的代码. 
       2005-6-14: 为CloseInterface()函数添加默认参数, 决定是否需要调用回调. 
 ************************************************************************************/ 
 
 
#if !defined(AFX_COMMINTERFACE_H__1F66DAE4_677B_43D0_8384_ED8D698B9892__INCLUDED_) 
#define AFX_COMMINTERFACE_H__1F66DAE4_677B_43D0_8384_ED8D698B9892__INCLUDED_ 
 
#if _MSC_VER > 1000 
#pragma once 
#endif // _MSC_VER > 1000 
 
#include 	// Support for windows socket 
 
/////////////////////////////////////////////////////////// 
// Some macros 
/////////////////////////////////////////////////////////// 
#define INTERFACE_MINTYPE		0	// Min interface type 
#define INTERFACE_COMMPORT		0	// Commport interface 
#define INTERFACE_TCPSERVER		1	// TcpServer interface 
#define INTERFACE_TCPCLIENT		2	// TcpClient interface 
#define INTERFACE_E1            3   // E1 interface /* lipf 2003-12-23 */ 
#define INTERFACE_UDP           4   // Udp interface 
#define INTERFACE_MAXTYPE		4	// Max interface type 
 
// ============ D.H 2004-11-5 15:45:03 ============ 
// Both the send/recv buffer size are defined as 
//  8k, if you want larger, just modify this. 
// ================================================ 
#define RECVBUF_SIZE	(8 * 1024)	// receive buffer size 8k 
#define SENDBUF_SIZE	(8 * 1024)	// send buffer size 8k 
 
/////////////////////////////////////////////////////////// 
// Some user-defined messages 
/////////////////////////////////////////////////////////// 
#define TM_START_SENDCOMMANDLOOP	(WM_USER + 1000)	// Thread message 
#define TM_START_LOOP_MODE_0		(WM_USER + 1001)	// Thread message 
#define TM_START_LOOP_MODE_1		(WM_USER + 1002)	// Thread message 
#define TM_START_LOOP_MODE_2		(WM_USER + 1002)	// Thread message 
														// Equal to TM_START_LOOP_MODE_1 
														//  same process function 
#define TM_START_LOOP_MODE_3        (WM_USER + 1003)    // For E1 /* lipf 2003-12-23 */ 
#define TM_START_LOOP_MODE_4        (WM_USER + 1004)    // Thread message 
 
// Declare some classes first 
class CInterfaceSendCmdThread; 
class CInterfaceListenSocket; 
class CInterfaceDataSocket; 
class CInterfaceUdpSocket; 
 
/////////////////////////////////////////////////////////// 
// Communication Interface Class(Main class) 
/////////////////////////////////////////////////////////// 
class CCommInterface 
{ 
	/////////////////////////////////////////////////////////// 
	// Used by all types of interfaces 
	/////////////////////////////////////////////////////////// 
protected: 
	// 命令队列节点的数据结构 
	typedef struct _COMMAND_LIST_NODE 
	{ 
		BYTE *pbyCommand; 
		int nLenOfCmd; 
		struct _COMMAND_LIST_NODE *pNext; 
	}COMMAND_LIST_NODE; 
 
public: 
	CCommInterface(int nCommMode); 
	virtual ~CCommInterface(); 
 
 
	// 获取接口类型 
	int GetCommMode(void) const { return m_nCommMode; } 
	// 添加该命令到发送队列 
	BOOL AppendCmdToSend(const BYTE byBuf[], int nLen); 
	// 优先发送该条命令 
	BOOL InsertCmdToSend(const BYTE byBuf[], int nLen); 
	// 删除所有命令 
	void DeleteAllCmds(void); 
	// 关闭接口 
	BOOL CloseInterface(BOOL bInvokeCallback = TRUE); 
	// 设置命令的最小发送间隔 
    void SetMinIntervalBetweenCmds(DWORD dwInterval) { 
        m_dwMinIntervalBetweenCmds = dwInterval; 
    } 
	// 获取命令的最小发送间隔 
	DWORD GetMinIntervalBetweenCmds(void) const	{ 
        return m_dwMinIntervalBetweenCmds; 
    } 
 
	// 获取版本信息 
	DWORD GetVersionInfo(BOOL bShowMsgbox) const; 
 
 
protected: 
	// 取出第一条命令, 去发送 
	BOOL GetCmdToSend(BYTE byBuf[], int& nLen); 
	// 删掉第一条命令 (已成功发送时调用一次) 
	BOOL DeleteFirstCmd(void); 
 
	// 获取回调函数地址 
	void* GetDataProcAddr(void) const { return m_pfnDataProcCallback; } 
	// 获取回调函数的第三个参数 
	void* GetCallbackParam(void) const { return m_pParamCallback; } 
 
	HANDLE m_hEvtCanGetCmdToSend; // 可以从命令队列中取出命令去发送 
	HANDLE m_hEvtCanAddCmdToSend; // 可以向命令队列中增加命令 
 
protected: 
	int m_nCommMode; // 接口类型: (3, 4 are not completed yet.) 
					 // 0 - RS232 (Duplex); 
					 // 1 - WinSock TCP/IP Server; 
					 // 2 - WinSock TCP/IP Client; 
					 // 3 - Modem(Dialed thru RS232, duplex); 
					 // 4 - RS485 (Semiduplex); 
 
	DWORD m_dwMinIntervalBetweenCmds;	// 命令的最小发送间隔 
 
	COMMAND_LIST_NODE *m_pCmdListHead, *m_pCmdListTail;	// 待发命令队列的头尾指针 
	CInterfaceSendCmdThread *m_pSendCmdThrd;	// 发送命令的线程 
 
	void *m_pfnInterfaceOpenCallback;	// 接口打开回调函数的地址 
	void *m_pfnInterfaceCloseCallback;	// 接口关闭回调函数的地址 
	void *m_pfnDataProcCallback;		// 数据处理回调函数的地址 
	void *m_pParamCallback;				// 回调函数的第三个参数 
 
 
//----------------------------------------------------------------------------------- 
	/////////////////////////////////////////////////////////// 
	// m_nCommMode = 0 
	// Following code is used by RS232 mode 
	/////////////////////////////////////////////////////////// 
public: 
	// 打开串口, 同时传递回调参数 
	BOOL CreateInterface_CommPort(int nCommPort, 
								  const void *pfnInterfaceOpenCallback, 
								  const void *pfnInterfaceCloseCallback, 
								  const void *pfnDataProcCallback, 
								  const void *pParamCallback); 
	// 配置及获取串口参数 
	BOOL SetCommState(const DCB *pdcb) const; 
	BOOL GetCommState(const DCB *pdcb) const; 
	// 配置及获取串口超时 
	BOOL SetCommTimeouts(const COMMTIMEOUTS *ptmo) const; 
	BOOL GetCommTimeouts(const COMMTIMEOUTS *ptmo) const; 
 
protected: 
	// 获取串口句柄 
	HANDLE GetCommPortHandle(void) const { return m_hCommPort; } 
	// 关闭串口 
	BOOL CloseInterface_CommPort(BOOL bInvokeCallback); 
 
private: 
	// 保存读串口线程的OVERLAPPED结构指针, user should not call this! 
	void SaveOverlappedReadComm(const OVERLAPPED *polRead) { 
        m_polReadComm = (OVERLAPPED *) polRead; 
    } 
 
protected: 
	int m_nCommPort;				// Commport index (of coz, 1-based integer) 
	HANDLE m_hCommPort;				// The commport handle 
 
	OVERLAPPED *m_polReadComm;		// 读串口线程的OVERLAPPED结构指针 
	CWinThread *m_pReadCommThrd;	// 读串口线程 
 
 
//----------------------------------------------------------------------------------- 
	/////////////////////////////////////////////////////////// 
	// m_nCommMode = 1 
	// Used by WinSock Server mode 
	/////////////////////////////////////////////////////////// 
public: 
	// 打开接口socket, 并启动监听 
	BOOL CreateInterface_TcpServer(unsigned int nListenPort, 
								   const void *pfnInterfaceOpenCallback, 
								   const void *pfnInterfaceCloseCallback, 
								   const void *pfnDataProcCallback, 
								   const void *pParamCallback); 
protected: 
	// 获取DataSocket 
	CInterfaceDataSocket* GetDataSocket(void) const { return m_pDataSock; } 
	// 关闭接口 (Tcp Server 模式) 
	BOOL CloseInterface_TcpServer(BOOL bInvokeCallback); 
	// 处理监听socket的OnAccept(..) 
	BOOL ProcessSocketAccept(void); 
	// 处理数据socket的OnReceive(..) 
	BOOL ProcessSocketReceive(void) const; 
	// 处理数据socket的OnClose(..) 
	BOOL ProcessSocketClose(void); 
 
protected: 
	unsigned int m_nListenPort; // 启动监听的端口 
	CInterfaceListenSocket *m_pListenSock; // 监听连接的Socket 
	CInterfaceDataSocket *m_pDataSock; // 数据Socket 
 
 
//----------------------------------------------------------------------------------- 
	/////////////////////////////////////////////////////////// 
	// m_nCommMode = 2 
	// Used by WinSock Client mode 
	// (与模式1共用一些函数和变量) 
	/////////////////////////////////////////////////////////// 
public: 
	// 打开接口socket, 并进行连接 
	BOOL CreateInterface_TcpClient(CString csServerIp, // Server's IP addr 
								   unsigned int nListenPort, // Server's listen port 
								   const void *pfnInterfaceOpenCallback, 
								   const void *pfnInterfaceCloseCallback, 
								   const void *pfnDataProcCallback, 
								   const void *pParamCallback); 
 
	// liep 2003-11-24 15:05:29 
	void GetSockName(CString& csIP, UINT& nPort) const; 
protected: 
	// 关闭接口 (Tcp Client 模式) 
	BOOL CloseInterface_TcpClient(BOOL bInvokeCallback); 
	// 处理数据socket的OnConnect(..) 
	BOOL ProcessSocketConnect(void); 
 
protected: 
	CString m_csServerIp;	// 服务端的IP地址 
 
//----------------------------------------------------------------------------------- 
    ////////////////////////////////////////////////////////////////////////// 
    // m_nCommMode = 3 
    // Following code is used by E1 mode/* lipf 2003-12-23 */ 
    ////////////////////////////////////////////////////////////////////////// 
public: 
    BOOL CreateInterface_E1(unsigned int nCardID, // E1 Card Num 1--4 
                            unsigned int nSlotID, // E1's Time Slot 0--31 
                            const void *pfnInterfaceOpenCallback, 
                            const void *pfnInterfaceCloseCallback, 
                            const void *pfnDataProcCallback, 
                            const void *pParamCallback); 
protected: 
    // 获取E1句柄 
     HANDLE GetE1Handle(void) const { return m_hE1Handle; } 
    // 关闭E1 
    BOOL CloseInterface_E1(BOOL bInvokeCallback); 
    void SaveOverlappedReadE1(const OVERLAPPED *polRead) { 
         m_polReadE1 = (OVERLAPPED *) polRead; 
    } 
protected: 
    int m_nCardID;                  // range of 1 to 4 
    int m_nSlotID;                  // range of 0 to 31 
    HANDLE m_hE1Handle; 
    OVERLAPPED *m_polReadE1;		// 读E1线程的OVERLAPPED结构指针 
    CWinThread *m_pReadE1Thrd;	// 读E1线程 
 
 
 
//----------------------------------------------------------------------------------- 
    //////////////////////////////////////////////////////////// 
    // D.H 2004-8-12 15:49:24 
    // m_nCommMode = 4 
    // Following code is used by Udp mode 
    // 备注: 因为Udp socket可能每条命令发给不同的对象(Host&Port), 
    //  所以需要把每条命令的发送目的记录下来, 可是记录在哪儿呢? 
    //  终于, 决定把这个信息记录在每个数据包里面, 所以需要对函数 
    //  AppendCmdToSend()和InsertCmdToSend()做一些修改... 
    //////////////////////////////////////////////////////////// 
public: 
    BOOL CreateInterface_Udp(UINT nPort, 
                             const void *pfnInterfaceOpenCallback, 
                             const void *pfnInterfaceCloseCallback, 
                             const void *pfnDataProcCallback, 
                             const void *pParamCallback); 
    LPCTSTR SetUdpTargetHost(LPCTSTR lpszTargetHost); 
    UINT SetUdpTargetPort(UINT nTargetPort); 
    LPCTSTR GetUdpTargetHost(void) const { return m_csTargetHost; } 
    UINT GetUdpTargetPort(void) const { return m_nTargetPort; } 
 
protected: 
    UINT m_nUdpPort; // the udp port we opened 
    CInterfaceUdpSocket *m_pUdpSock; 
    CString m_csTargetHost; // the target host we will send data to 
    UINT m_nTargetPort; // the port of the target host 
 
protected: 
    BOOL CloseInterface_Udp(BOOL bInvokeCallback); 
    CInterfaceUdpSocket* GetUdpSocket(void) const { return m_pUdpSock; } 
    // 处理Udp socket数据到 
    BOOL ProcessUdpSocketReceiveFrom(void) const; 
     
	/////////////////////////////////////////////////////////// 
	// Some friend classes and functions 
	// David 2003-4-30 5:49:57 PM 
	/////////////////////////////////////////////////////////// 
	friend class CInterfaceListenSocket; 
	friend class CInterfaceDataSocket; 
	friend class CInterfaceSendCmdThread; 
    friend class CInterfaceUdpSocket; 
	friend UINT ReadCommThread(LPVOID pParam); 
    friend UINT ReadE1Thread(LPVOID pParam); 
}; 
 
//----------------------------------------------------------------------------------- 
/////////////////////////////////////////////////////////// 
// 发送命令的线程类(辅助的类, 串口操作时使用) 
/////////////////////////////////////////////////////////// 
class CInterfaceSendCmdThread : public CWinThread 
{ 
	DECLARE_DYNCREATE(CInterfaceSendCmdThread) 
protected: 
	CInterfaceSendCmdThread();           // protected constructor used by dynamic creation 
 
// Attributes 
protected: 
	OVERLAPPED m_olWrite; // 声明为public是为了能从外部将其删除, 避免句柄泄漏 
	CCommInterface *m_pInfc; // 接口的指针 
 
// Operations 
protected: 
	// 设置接口的指针 
    void SetInterfaceHandle(const CCommInterface *pInfc) { 
        m_pInfc = (CCommInterface *) pInfc; 
    } 
 
// Overrides 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CInterfaceSendCmdThread) 
	public: 
	virtual BOOL InitInstance(); 
	virtual int ExitInstance(); 
	//}}AFX_VIRTUAL 
 
// Implementation 
public: 
	virtual ~CInterfaceSendCmdThread(); 
 
protected: 
	// Generated message map functions 
	//{{AFX_MSG(CInterfaceSendCmdThread) 
		// NOTE - the ClassWizard will add and remove member functions here. 
	//}}AFX_MSG 
	/////////////////////////////////////////////////////////// 
	// 启动发送命令循环 
	/////////////////////////////////////////////////////////// 
	afx_msg LRESULT Start_SendCommandLoop(WPARAM wParam, LPARAM lParam); 
	// 不同接口类型对应的发送命令循环函数 
	afx_msg LRESULT SendCommandLoop_Mode0(WPARAM wParam, LPARAM lParam); 
	afx_msg LRESULT SendCommandLoop_Mode1(WPARAM wParam, LPARAM lParam); 
    afx_msg LRESULT SendCommandLoop_Mode3(WPARAM wParam, LPARAM lParam); 
    afx_msg LRESULT SendCommandLoop_Mode4(WPARAM wParam, LPARAM lParam); 
	DECLARE_MESSAGE_MAP() 
 
	/////////////////////////////////////////////////////////// 
	friend class CCommInterface; 
}; 
 
//----------------------------------------------------------------------------------- 
/////////////////////////////////////////////////////////// 
// 监听socket类 (辅助的类, Tcp server模式下使用) 
/////////////////////////////////////////////////////////// 
class CInterfaceListenSocket : public CAsyncSocket 
{ 
// Attributes 
protected: 
	CCommInterface *m_pInfc; 
 
// Operations 
public: 
	CInterfaceListenSocket(); 
	CInterfaceListenSocket(CCommInterface *pInfc); 
	virtual ~CInterfaceListenSocket(); 
 
// Overrides 
public: 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CInterfaceListenSocket) 
	public: 
	virtual void OnAccept(int nErrorCode); 
	//}}AFX_VIRTUAL 
 
	// Generated message map functions 
	//{{AFX_MSG(CInterfaceListenSocket) 
		// NOTE - the ClassWizard will add and remove member functions here. 
	//}}AFX_MSG 
 
// Implementation 
protected: 
}; 
 
 
//----------------------------------------------------------------------------------- 
/////////////////////////////////////////////////////////// 
// 数据socket类 (辅助的类, Tcp Server/Client 模式下使用) 
/////////////////////////////////////////////////////////// 
class CInterfaceDataSocket : public CAsyncSocket 
{ 
// Attributes 
protected: 
	CCommInterface *m_pInfc; 
     
protected: 
    // D.H 2004-6-21 11:24:32 
    // 用来判断是否能够调用Send()发送数据的事件 
    HANDLE m_hEvtSocketCanSend; 
public: 
    HANDLE GetEvtHandle_SocketCanSend(void) const { return m_hEvtSocketCanSend; } 
 
// Operations 
public: 
	CInterfaceDataSocket(); 
	CInterfaceDataSocket(CCommInterface *pInfc); 
	virtual ~CInterfaceDataSocket(); 
 
// Overrides 
public: 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CInterfaceDataSocket) 
	public: 
	virtual void OnReceive(int nErrorCode); 
	virtual void OnClose(int nErrorCode); 
	virtual void OnConnect(int nErrorCode); 
    virtual void OnSend(int nErrorCode); 
	//}}AFX_VIRTUAL 
 
	// Generated message map functions 
	//{{AFX_MSG(CInterfaceDataSocket) 
		// NOTE - the ClassWizard will add and remove member functions here. 
	//}}AFX_MSG 
 
// Implementation 
protected: 
}; 
 
 
//------------------------------------------------------------------------------------- 
//////////////////////////////////////////////////////////// 
// Udp socket类 (INTERFACE_UDP模式下使用) 
//////////////////////////////////////////////////////////// 
class CInterfaceUdpSocket : public CAsyncSocket 
{ 
// Attributes 
protected: 
    CCommInterface *m_pInfc; 
 
// Operations 
public: 
    CInterfaceUdpSocket(); 
    CInterfaceUdpSocket(CCommInterface *pInfc); 
    virtual ~CInterfaceUdpSocket(); 
     
// Overrides 
public: 
    // ClassWizard generated virtual function overrides 
    //{{AFX_VIRTUAL(CInterfaceDataSocket) 
public: 
    virtual void OnReceive(int nErrorCode); 
    //}}AFX_VIRTUAL 
     
    // Generated message map functions 
    //{{AFX_MSG(CInterfaceDataSocket) 
    // NOTE - the ClassWizard will add and remove member functions here. 
    //}}AFX_MSG 
     
    // Implementation 
protected: 
}; 
 
#endif // !defined(AFX_COMMINTERFACE_H__1F66DAE4_677B_43D0_8384_ED8D698B9892__INCLUDED_)