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


/************************************************************************************ 
 * 文件名: CommInterface.cpp 
 * 版权: 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. 
       2003-1-7:  0 修改E1方式打开时的时隙号问题, 配置时隙号码-1 
       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()函数添加默认参数, 决定是否需要调用回调. 
 ************************************************************************************/ 
 
 
#include "stdafx.h" 
#include "CommInterface.h" 
 
// D.H 2004-8-12 14:27:36 
// Plz note!! 
// If you wanna use E1 communication mode, (which is rarely used) 
//  you must define the macro below, or, the mode does not work. 
#ifdef C7A43868_D29A_4404_9BFD_698A970F8614 
    #include "ntddser.h" 
    #include "cardtioctl.h" 
    #include "WINIOCTL.h" 
#endif 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
 
/////////////////////////////////////////////////////////// 
// Some non-member functions 
/////////////////////////////////////////////////////////// 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 串口收数线程函数 
// 参数说明: 接口实例指针 
// 返回值: No use 
// 创建人: DavidHowe;  创建时间: 2003-4-28 4:10:42 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
UINT ReadCommThread(LPVOID pParam) 
{ 
	CCommInterface *pInfc = (CCommInterface *) pParam; 
 
	// Allocate receive buffer 
	BYTE byRecvBuf[RECVBUF_SIZE]; 
 
	DWORD dwBytesRead = 0; 
	DWORD dwError, dwEvent; 
 
	// Overlapped structure 
	OVERLAPPED olRead; 
	memset(&olRead, 0, sizeof(OVERLAPPED)); 
	olRead.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); 
 
	/////////////////////////////////////////////////////////// 
	// David 2003-4-28 3:05:07 PM 
	// Save the olRead in the interface, when the thread is 
	//  terminated, close the olRead.hEvent's handle. 
	// Add this line to fix a "handle leak" bug. 
	/////////////////////////////////////////////////////////// 
	pInfc->SaveOverlappedReadComm(&olRead); 
 
	// Get the comm's handle 
	HANDLE hComm = pInfc->GetCommPortHandle(); 
 
	// Set comm mask 
	::SetCommMask(hComm, EV_RXCHAR); 
 
	// Get the data-proc callback function's pointer and the "pParamCallback" 
	//  param of current interface instance 
	void (*pfnDataProc)(BYTE [], int, void *) = 
		(void(*)(BYTE [], int, void *)) pInfc->GetDataProcAddr(); 
	void *pParamCallback = pInfc->GetCallbackParam(); 
 
	/////////////////////////////////////////////////////////// 
	// Read-comm infinite loop 
	/////////////////////////////////////////////////////////// 
	while(TRUE) 
	{ 
		if(! ::WaitCommEvent(hComm, &dwEvent, &olRead)) 
		{ 
			if(GetLastError() != ERROR_IO_PENDING) 
			{ 
				::ClearCommError(hComm, &dwError, NULL); 
				continue; 
			} 
			::WaitForSingleObject(olRead.hEvent, INFINITE); 
			::ResetEvent(olRead.hEvent); 
			if(dwEvent & EV_RXCHAR) 
			{ 
				if(! ::ReadFile(hComm, byRecvBuf, RECVBUF_SIZE, &dwBytesRead, 
					&olRead)) 
				{ 
					if(! ::GetOverlappedResult(hComm, &olRead, &dwBytesRead, TRUE)) 
						continue; 
					// Process Data 
					pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
				} 
				else 
				{ 
					// Process Data 
					pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
				} 
			} 
		} 
		else 
		{ 
			::ResetEvent(olRead.hEvent); 
			if(dwEvent & EV_RXCHAR) 
			{ 
				if(! ::ReadFile(hComm, byRecvBuf, RECVBUF_SIZE, &dwBytesRead, 
					&olRead)) 
				{ 
					if(! ::GetOverlappedResult(hComm, &olRead, &dwBytesRead, TRUE)) 
						continue; 
					// Process Data 
					pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
				} 
				else 
				{ 
					// Process Data 
					pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
				} 
			} 
		} 
	} 
 
	return 0L; // Never reaches here 
} 
 
/************************************************************************************* 
** Description: E1读线程 
** Parameters:  
** Return:  
** Author: lipf;  Date: 2003-12-23 14:49:18;  Location: Office 
** Misc:  
**************************************************************************************/ 
UINT ReadE1Thread(LPVOID pParam) 
{ 
#ifndef C7A43868_D29A_4404_9BFD_698A970F8614 
    return 0L; 
#else 
    CCommInterface *pInfc = (CCommInterface *) pParam; 
    DWORD dwEvent, dwBytesRead=0; 
    BYTE byRecvBuf[RECVBUF_SIZE]; 
    ULONG rxMask = EV_RXCHAR; 
    ULONG nOutput; 
    OVERLAPPED olE1Read; 
    memset(&olE1Read, 0, sizeof(OVERLAPPED)); 
    olE1Read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);	// 重叠结构初始化 
    pInfc->SaveOverlappedReadE1(&olE1Read);     
    // Get the E1's handle 
    HANDLE hE1 = pInfc->GetE1Handle(); 
 
    if(!DeviceIoControl(hE1, IOCTL_SERIAL_SET_WAIT_MASK, &rxMask, 
        sizeof(ULONG),NULL, 0,&nOutput,NULL)) 
    { 
        TRACE("E1SCSetEvent 失败\n"); 
    } 
    // Get the data-proc callback function's pointer and the "pParamCallback" 
    //  param of current interface instance 
    void (*pfnDataProc)(BYTE [], int, void *) = 
        (void(*)(BYTE [], int, void *)) pInfc->GetDataProcAddr(); 
     
    void *pParamCallback = pInfc->GetCallbackParam(); 
 
    while(TRUE) 
    {        
        if (!DeviceIoControl(hE1, IOCTL_SERIAL_WAIT_ON_MASK,NULL,0,&dwEvent, 
            sizeof(DWORD), &nOutput,&olE1Read)) 
        { 
            if(GetLastError()!=ERROR_IO_PENDING)	// 串口异常处理 
            { 
                continue; 
            }			 
             
            ::WaitForSingleObject(olE1Read.hEvent, INFINITE);	// 等待数据到 
            ::ResetEvent(olE1Read.hEvent); 
                       
            if(dwEvent & EV_RXCHAR) 
            { 
                if (!ReadFile(hE1, byRecvBuf, RECVBUF_SIZE, &dwBytesRead, &olE1Read))	// 读整个数据包 
                { 
//DEL                     if (GetLastError()!=ERROR_IO_PENDING)  
//DEL                         continue; 
                    if (!GetOverlappedResult(hE1, &olE1Read, 
                        &dwBytesRead, TRUE)) 
                        continue; 
                     
                    pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
                } 
                else 
                { 
                    pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
                } 
            } 
        } 
        else 
        { 
            ::ResetEvent(olE1Read.hEvent); 
            if(dwEvent & EV_RXCHAR) 
            { 
                if (!ReadFile(hE1, byRecvBuf, RECVBUF_SIZE, &dwBytesRead, &olE1Read))	// 读整个数据包 
                { 
                    if (!GetOverlappedResult(hE1, &olE1Read, 
                        &dwBytesRead, TRUE)) 
                        continue; 
                     
                    pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
                } 
                else 
                { 
                    pfnDataProc(byRecvBuf, dwBytesRead, pParamCallback); 
                } 
            } 
        } 
    } 
    return 0l; 
#endif // C7A43868_D29A_4404_9BFD_698A970F8614 
} 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CCommInterface::CCommInterface(int nCommMode) 
{ 
	// 
	// Initial vars 
	// 
	ASSERT(nCommMode >= INTERFACE_MINTYPE && nCommMode <= INTERFACE_MAXTYPE); 
	m_nCommMode = nCommMode; 
	m_pSendCmdThrd = NULL; 
	m_hCommPort = NULL; 
	m_pfnInterfaceOpenCallback = NULL; 
	m_pfnInterfaceCloseCallback = NULL; 
	m_pfnDataProcCallback = NULL; 
	m_pParamCallback = NULL; 
	m_pReadCommThrd = NULL; 
	m_polReadComm = NULL; 
	m_hEvtCanGetCmdToSend = ::CreateEvent(NULL, FALSE, TRUE, NULL); 
	m_hEvtCanAddCmdToSend = ::CreateEvent(NULL, TRUE, TRUE, NULL); 
	m_dwMinIntervalBetweenCmds = 50; // A default value, developer should modify 
									 //  this by calling SetMinIntervalBetweenCmds(..) 
	m_pListenSock = NULL; 
	m_pDataSock = NULL; 
 
    // E1 Param/* lipf 2003-12-23 */ 
    m_hE1Handle = NULL; 
    m_pReadE1Thrd = NULL; 
    m_polReadE1 = NULL; 
 
    m_nUdpPort = 0; 
    m_pUdpSock = NULL; 
    m_csTargetHost = _T(""); 
    m_nTargetPort = 0; 
 
	// 
	// 创建待发送命令队列 
	// 
	m_pCmdListHead = new COMMAND_LIST_NODE; 
	m_pCmdListHead->pbyCommand = NULL; 
	m_pCmdListHead->nLenOfCmd = 0; 
	m_pCmdListHead->pNext = NULL; 
	m_pCmdListTail = m_pCmdListHead; // 初始为空, 尾指向头 
} 
 
CCommInterface::~CCommInterface() 
{ 
	// 关闭接口 
	CloseInterface(); 
 
	// 
	// 释放命令队列 
	// 
	COMMAND_LIST_NODE *p; 
	while(m_pCmdListHead->pNext) 
	{ 
		p = m_pCmdListHead; 
		m_pCmdListHead = m_pCmdListHead->pNext; 
 
		if(p->pbyCommand) delete p->pbyCommand; 
		delete p; 
	} 
	if(m_pCmdListHead->pbyCommand) delete m_pCmdListHead->pbyCommand; 
	delete m_pCmdListHead; 
 
	// 删除 
	::CloseHandle(m_hEvtCanGetCmdToSend); 
	::CloseHandle(m_hEvtCanAddCmdToSend); 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 获取版本信息 
// 参数说明: 是否显示版本消息 
// 返回值: 版本号(高16bits是主版本号, 低16bits是次版本号) 
// 创建人: DavidHowe;  创建时间: 2003-5-4 12:56:06;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
DWORD CCommInterface::GetVersionInfo(BOOL bShowMsgbox) const 
{ 
	if(bShowMsgbox) 
	{ 
		CString csMsg, csTmp; 
		csTmp.Format("Last build: %s %s     \n\n", __DATE__, __TIME__); 
		csMsg = "Module: CCommInterface\n"; 
		csMsg += "Version: 1.5\n"; 
		csMsg += csTmp; 
		csMsg += "Author: David Howe\n"; 
		csMsg += "E-mail: davidhowe@sina.com\n"; 
		AfxMessageBox(csMsg, MB_ICONINFORMATION | MB_OK); 
	} 
 
	return 0x00010005; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 关闭接口(根据接口类型调用相应的函数) 
// 参数说明:  
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 9:42:31 AM;  地点: Xi'an 
// 备注/修改记录: 用统一的函数关闭接口. 
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CloseInterface(BOOL bInvokeCallback) 
{ 
	if(m_nCommMode == INTERFACE_COMMPORT) return CloseInterface_CommPort(bInvokeCallback); 
	else if(m_nCommMode == INTERFACE_TCPSERVER) return CloseInterface_TcpServer(bInvokeCallback); 
	else if(m_nCommMode == INTERFACE_TCPCLIENT) return CloseInterface_TcpClient(bInvokeCallback); 
    else if (m_nCommMode == INTERFACE_E1) return CloseInterface_E1(bInvokeCallback); 
    else if (m_nCommMode == INTERFACE_UDP) return CloseInterface_Udp(bInvokeCallback); 
 
	return FALSE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 添加该命令到发送队列的队尾 
// 参数说明: 命令buf, 命令长度 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-23 3:53:44 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::AppendCmdToSend(const BYTE byBuf[], int nLen) 
{ 
	if(byBuf == NULL) 
	{ 
		TRACE("Interface::Command buffer is empty, add command failed.\n"); 
        ASSERT(FALSE); 
		return FALSE; 
	} 
	if(nLen <= 0 || nLen > SENDBUF_SIZE) 
	{ 
		TRACE("Interface::Command must be short than %d bytes.\n", SENDBUF_SIZE); 
        ASSERT(FALSE); 
		return FALSE; 
	} 
 
    // 
    // Copy the command 
	// 
    COMMAND_LIST_NODE *pCmdNode = NULL; 
    if (m_nCommMode == INTERFACE_UDP) // For UDP comm mode 
    { 
        if (nLen > SENDBUF_SIZE - 32) 
        { 
            TRACE("Interface::Out of send buffer in udp mode!\n"); 
            ASSERT(FALSE); 
            return FALSE; 
        } 
        if (m_nTargetPort == 0) 
        { 
            TRACE("Interface::You must set the host address and host port first!\n"); 
            ASSERT(FALSE); 
            return FALSE; 
        } 
 
        // D.H 2004-8-13 9:50:44 
        // 注意, 对于每条命令, 都要保存发送目的信息 
        pCmdNode = new COMMAND_LIST_NODE; 
        pCmdNode->pbyCommand = new BYTE[nLen + m_csTargetHost.GetLength() + 1 + 
            sizeof(DWORD)]; 
        memcpy(pCmdNode->pbyCommand, (LPCTSTR) m_csTargetHost, m_csTargetHost.GetLength()); 
        pCmdNode->pbyCommand[m_csTargetHost.GetLength()] = '\0'; 
        memcpy(pCmdNode->pbyCommand + m_csTargetHost.GetLength() + 1, &m_nTargetPort, 
            sizeof(DWORD)); 
        memcpy(pCmdNode->pbyCommand + m_csTargetHost.GetLength() + 1 + sizeof(DWORD), 
            byBuf, nLen); 
        pCmdNode->nLenOfCmd = nLen + m_csTargetHost.GetLength() + 1 + sizeof(DWORD); 
        pCmdNode->pNext = NULL; 
    } 
    else // All comm mode but UDP 
    { 
        pCmdNode = new COMMAND_LIST_NODE; 
        pCmdNode->pbyCommand = new BYTE[nLen]; 
        memcpy(pCmdNode->pbyCommand, byBuf, nLen); 
        pCmdNode->nLenOfCmd = nLen; 
        pCmdNode->pNext = NULL; 
    } 
 
    ::WaitForSingleObject(m_hEvtCanGetCmdToSend, INFINITE); 
 
	// Wait until we can add the command 
	::WaitForSingleObject(m_hEvtCanAddCmdToSend, INFINITE); 
    ::ResetEvent(m_hEvtCanAddCmdToSend); 
 
	/////////////////////////////////////////////////////////// 
	// 使用事件, 为了在添加命令的过程中不让发送线程取命令 
	/////////////////////////////////////////////////////////// 
 
    // 
	// Append to list 
	// 
	if(m_pCmdListHead->pNext == NULL) // List is empty yet 
	{ 
		m_pCmdListHead->pNext = pCmdNode; 
		m_pCmdListTail = pCmdNode; 
	} 
	else // List is not empty 
	{ 
		m_pCmdListTail->pNext = pCmdNode; 
		m_pCmdListTail = pCmdNode; 
	} 
 
	// 事件置信号态 
	::SetEvent(m_hEvtCanGetCmdToSend); 
    ::SetEvent(m_hEvtCanAddCmdToSend); 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 插入一条命令到队头, 优先发送该条命令 
// 参数说明: 命令buf, 命令长度 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-23 4:30:19 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::InsertCmdToSend(const BYTE byBuf[], int nLen) 
{ 
	if(byBuf == NULL) 
	{ 
		TRACE("Interface::Command buffer is empty, add command failed.\n"); 
        ASSERT(FALSE); 
		return FALSE; 
	} 
	if(nLen <= 0 || nLen > SENDBUF_SIZE) 
	{ 
		TRACE("Interface::Command must be short than %d bytes.\n", SENDBUF_SIZE); 
        ASSERT(FALSE); 
		return FALSE; 
	} 
 
    // 
    // Copy the command 
    // 
    COMMAND_LIST_NODE *pCmdNode = NULL; 
    if (m_nCommMode == INTERFACE_UDP) // For UDP comm mode 
    { 
        if (nLen > SENDBUF_SIZE - 32) 
        { 
            TRACE("Interface::Out of send buffer in udp mode!\n"); 
            ASSERT(FALSE); 
            return FALSE; 
        } 
        if (m_nTargetPort == 0) 
        { 
            TRACE("Interface::You must set the host address and host port first!\n"); 
            ASSERT(FALSE); 
            return FALSE; 
        } 
         
        // D.H 2004-8-13 9:50:44 
        // 注意, 对于每条命令, 都要保存发送目的信息 
        pCmdNode = new COMMAND_LIST_NODE; 
        pCmdNode->pbyCommand = new BYTE[nLen + m_csTargetHost.GetLength() + 1 + 
            sizeof(DWORD)]; 
        memcpy(pCmdNode->pbyCommand, (LPCTSTR) m_csTargetHost, m_csTargetHost.GetLength()); 
        pCmdNode->pbyCommand[m_csTargetHost.GetLength()] = '\0'; 
        memcpy(pCmdNode->pbyCommand + m_csTargetHost.GetLength() + 1, &m_nTargetPort, 
            sizeof(DWORD)); 
        memcpy(pCmdNode->pbyCommand + m_csTargetHost.GetLength() + 1 + sizeof(DWORD), 
            byBuf, nLen); 
        pCmdNode->nLenOfCmd = nLen + m_csTargetHost.GetLength() + 1 + sizeof(DWORD); 
        pCmdNode->pNext = NULL; 
    } 
    else // All comm mode but UDP 
    { 
        pCmdNode = new COMMAND_LIST_NODE; 
        pCmdNode->pbyCommand = new BYTE[nLen]; 
        memcpy(pCmdNode->pbyCommand, byBuf, nLen); 
        pCmdNode->nLenOfCmd = nLen; 
        pCmdNode->pNext = NULL; 
    } 
 
    ::WaitForSingleObject(m_hEvtCanGetCmdToSend, INFINITE); 
 
	// Wait until we can add the command 
	::WaitForSingleObject(m_hEvtCanAddCmdToSend, INFINITE); 
    ::ResetEvent(m_hEvtCanAddCmdToSend); 
 
	/////////////////////////////////////////////////////////// 
	// 使用事件, 为了在添加命令的过程中不让发送线程取命令 
	/////////////////////////////////////////////////////////// 
 
	// 
	// Insert into list 
	// 
	pCmdNode->pNext = m_pCmdListHead->pNext; 
	m_pCmdListHead->pNext = pCmdNode; 
	if(m_pCmdListTail == m_pCmdListHead) m_pCmdListTail = pCmdNode; 
 
	// 事件置信号态 
	::SetEvent(m_hEvtCanGetCmdToSend); 
    ::SetEvent(m_hEvtCanAddCmdToSend); 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 从命令队列中取出第一条命令 
// 参数说明: 输出命令的缓冲区, 输出命令的长度 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-28 5:14:47 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::GetCmdToSend(BYTE byBuf[], int& nLen) 
{ 
    ::WaitForSingleObject(m_hEvtCanAddCmdToSend, INFINITE); 
	// 此时不能进行增加命令操作 
	::ResetEvent(m_hEvtCanAddCmdToSend); 
 
	if(m_pCmdListHead->pNext == NULL) // No command to send 
	{ 
		nLen = 0; 
		::SetEvent(m_hEvtCanAddCmdToSend); 
		return FALSE; 
	} 
	else 
	{ 
		memcpy(byBuf, m_pCmdListHead->pNext->pbyCommand, 
			m_pCmdListHead->pNext->nLenOfCmd); 
		nLen = m_pCmdListHead->pNext->nLenOfCmd; 
		ASSERT(nLen <= SENDBUF_SIZE); 
		::SetEvent(m_hEvtCanAddCmdToSend); 
		return TRUE; 
	} 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 删掉第一条命令 (已成功发送时调用一次) 
// 参数说明:  
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-28 6:29:07 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::DeleteFirstCmd(void) 
{ 
	// No command to delete 
	if(m_pCmdListHead->pNext == NULL) 
	{ 
		TRACE("Interface::Delete command failed, sending-command list is empty.\n"); 
		return FALSE; 
	} 
 
	/////////////////////////////////////////////////////////// 
	// 删除命令的过程中不能添加或取出命令 
	/////////////////////////////////////////////////////////// 
 
    ::WaitForSingleObject(m_hEvtCanAddCmdToSend, INFINITE); 
	// 事件置非信号态 
//DEL 	::ResetEvent(m_hEvtCanGetCmdToSend); 
	::ResetEvent(m_hEvtCanAddCmdToSend); 
 
	// Head move on 
	COMMAND_LIST_NODE *p; 
	p = m_pCmdListHead->pNext; 
	m_pCmdListHead->pNext = m_pCmdListHead->pNext->pNext; 
	if(p->pbyCommand) delete p->pbyCommand; 
	delete p; 
 
	// 事件置信号态 
	::SetEvent(m_hEvtCanGetCmdToSend); 
	::SetEvent(m_hEvtCanAddCmdToSend); 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 删除所有命令 
// 参数说明:  
// 返回值:  
// 创建人: DavidHowe;  创建时间: 2003-4-29 5:02:33 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
void CCommInterface::DeleteAllCmds(void) 
{ 
	ASSERT(this != NULL); 
 
	/////////////////////////////////////////////////////////// 
	// 删除命令的过程中不能添加或取出命令 
	/////////////////////////////////////////////////////////// 
 
    ::WaitForSingleObject(m_hEvtCanAddCmdToSend, INFINITE); 
	// 事件置非信号态 
//DEL 	::ResetEvent(m_hEvtCanGetCmdToSend); 
	::ResetEvent(m_hEvtCanAddCmdToSend); 
 
	COMMAND_LIST_NODE *p, *q; 
	p = m_pCmdListHead->pNext; 
 
	if(! p) // Already empty 
	{ 
		// 事件置信号态 
		::SetEvent(m_hEvtCanGetCmdToSend); 
		::SetEvent(m_hEvtCanAddCmdToSend); 
		return; 
	} 
 
	while(p->pbyCommand != NULL) 
	{ 
		q = p; 
		p = p->pNext; 
 
		delete q->pbyCommand; 
		delete q; 
 
		if(! p) break; 
	} 
 
	m_pCmdListHead->pNext = NULL; 
	m_pCmdListTail = m_pCmdListHead; 
 
	// 事件置信号态 
	::SetEvent(m_hEvtCanGetCmdToSend); 
	::SetEvent(m_hEvtCanAddCmdToSend); 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 串口连接模式下, 打开接口的函数 
// 参数说明: 串口号(从1开始); 此串口收到数据时的回调函数; 备用参数 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-23 5:54:37 PM;  地点: Xi'an 
// 备注/修改记录: 要保证最多只有一个串口被打开 
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CreateInterface_CommPort(int nCommPort, 
											  const void *pfnInterfaceOpenCallback, 
											  const void *pfnInterfaceCloseCallback, 
											  const void *pfnDataProcCallback, 
											  const void *pParamCallback) 
{ 
	ASSERT(m_nCommMode == INTERFACE_COMMPORT); 
	if(m_nCommMode != INTERFACE_COMMPORT) return FALSE; 
 
	// Close previous if open 
	CloseInterface(); 
	ASSERT(m_hCommPort == NULL); 
 
	// The Interface Data Proc must be a valid pointer 
	ASSERT(pfnDataProcCallback != NULL); 
 
	if(nCommPort < 1 || nCommPort > 512) 
	{ 
		TRACE("Interface::Commport index out of range: %d\n", nCommPort); 
		return FALSE; 
	} 
 
	// Save the params 
	m_nCommPort = nCommPort; 
	m_pfnInterfaceOpenCallback = (void *) pfnInterfaceOpenCallback; 
	m_pfnInterfaceCloseCallback = (void *) pfnInterfaceCloseCallback; 
	m_pfnDataProcCallback = (void *) pfnDataProcCallback; 
	m_pParamCallback = (void *) pParamCallback; 
 
	// 
	// (Attempt to) open the commport 
	// 
	CString csCommStr; 
	csCommStr.Format("\\\\.\\COM%d", m_nCommPort); 
	HANDLE hComm = ::CreateFile(csCommStr, GENERIC_READ | GENERIC_WRITE, 0, 
		NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); 
	if(hComm == (HANDLE) -1) // Open failure 
	{ 
		m_hCommPort = NULL; 
		TRACE("Interface::Open commport failed: COM%d\n", nCommPort); 
 
		return FALSE; 
	} 
	else // Open success 
	{ 
		m_hCommPort = hComm; 
 
		// 
		// Config the commport using default settings 
		// 
		DCB dcb; 
		::GetCommState(m_hCommPort, &dcb); 
		dcb.BaudRate = CBR_9600; 
		dcb.ByteSize = 8; 
		dcb.Parity = NOPARITY; 
		dcb.StopBits = ONESTOPBIT; 
		if(! ::SetCommState(m_hCommPort, &dcb)) 
		{ 
			TRACE("Interface::Failed to use the default commport settings: 9600,n,8,1\n"); 
			CloseInterface(); 
			return FALSE; 
		} 
 
		// 
		// Config timeout settings using default settings 
		// 
		COMMTIMEOUTS tout; 
		::GetCommTimeouts(m_hCommPort, &tout); 
		tout.ReadIntervalTimeout = 20; // For CBR_9600 
		tout.ReadTotalTimeoutConstant = 0; 
		tout.ReadTotalTimeoutMultiplier = 0; 
		tout.WriteTotalTimeoutConstant = 0; 
		tout.WriteTotalTimeoutMultiplier = 0; 
		if(! ::SetCommTimeouts(m_hCommPort, &tout)) 
		{ 
			TRACE("Interface::Failed to use the default commport timeout settings!\n"); 
			CloseInterface(); 
			return FALSE; 
		} 
 
		// Purge commport 
		::PurgeComm(m_hCommPort, PURGE_RXCLEAR | PURGE_TXCLEAR); 
 
		// Start the read-comm thread! 
		m_pReadCommThrd = AfxBeginThread(ReadCommThread, this); 
 
		// 
		// Start the send-command thread! 
		// 
		m_pSendCmdThrd = (CInterfaceSendCmdThread *) AfxBeginThread( 
			RUNTIME_CLASS(CInterfaceSendCmdThread), 0, CREATE_SUSPENDED); 
		m_pSendCmdThrd->SetInterfaceHandle(this); 
		::ResumeThread(m_pSendCmdThrd->m_hThread); 
        BOOL bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
            TM_START_SENDCOMMANDLOOP, 0, 0); 
        // D.H 2004-8-11 15:59:59 
        // 添加对::PostThreadMessage()的返回判断处理, 以修正在Dll工程中 
        //  使用CCommInterface时不能启动发送数据线程的bug. 
        // {F598F388-14D8-464F-BE35-2CA67E1A978C} 
        while (! bRet) 
        { 
            Sleep(0); 
            bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
                TM_START_SENDCOMMANDLOOP, 0, 0); 
        } 
 
		// Call the Interface-Open callback 
		if(m_pfnInterfaceOpenCallback) 
		{ 
			void (*pfnCallback)(const void*) = 
				(void(*)(const void*))m_pfnInterfaceOpenCallback; 
			pfnCallback(m_pParamCallback); 
		} 
 
		return TRUE; 
	} 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 串口连接模式下, 关闭串口 
// 参数说明:  
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-24 6:10:00 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CloseInterface_CommPort(BOOL bInvokeCallback) 
{ 
	BOOL bRet = TRUE; 
	if(m_hCommPort != NULL) 
	{ 
		// Terminate read-comm thread 
		ASSERT(m_pReadCommThrd != NULL); 
		if(m_pReadCommThrd) 
		{ 
			if(m_pReadCommThrd->m_hThread) 
			{ 
				::TerminateThread(m_pReadCommThrd->m_hThread, 0); 
				delete m_pReadCommThrd; 
				m_pReadCommThrd = NULL; 
			} 
		} 
 
		// Terminate send-command thread 
		ASSERT(m_pSendCmdThrd != NULL); 
		if(m_pSendCmdThrd) 
		{ 
			::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
			::CloseHandle(m_pSendCmdThrd->m_olWrite.hEvent); // Prevent handle leak 
			delete m_pSendCmdThrd; 
			m_pSendCmdThrd = NULL; 
		} 
 
		// Close commport 
		ASSERT(m_hCommPort != NULL); 
		bRet = ::CloseHandle(m_hCommPort); 
		m_hCommPort = NULL; 
 
		// Close the event's handle (to prevent a handle leak) 
		ASSERT(m_polReadComm != NULL); 
		if(m_polReadComm) ::CloseHandle(m_polReadComm->hEvent); 
 
		// Call the Interface-Close callback 
		if(bInvokeCallback && m_pfnInterfaceCloseCallback) 
		{ 
			void (*pfnCallback)(const void*) = 
				(void(*)(const void*))m_pfnInterfaceCloseCallback; 
			pfnCallback(m_pParamCallback); 
		} 
 
		// Have a rest, or the same commport cannot be opened immediately 
		Sleep(50); 
	} 
 
	if(! bRet) TRACE("Interface::Close interface failed.\n"); 
 
	return bRet; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 配置串口参数 
// 参数说明: DCB 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-28 4:32:20 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::SetCommState(const DCB *pdcb) const 
{ 
	ASSERT(m_nCommMode == INTERFACE_COMMPORT); 
	ASSERT(m_hCommPort != NULL); 
	ASSERT(pdcb != NULL); 
	if(m_nCommMode != INTERFACE_COMMPORT) return FALSE; 
	if(m_hCommPort == NULL) return FALSE; 
	if(pdcb == NULL) return FALSE; 
 
	// 暂停线程 
	if(m_pReadCommThrd) 
	{ 
		if(m_pReadCommThrd->m_hThread) ::SuspendThread(m_pReadCommThrd->m_hThread); 
	} 
	if(m_pSendCmdThrd) 
	{ 
		if(m_pSendCmdThrd->m_hThread) ::SuspendThread(m_pSendCmdThrd->m_hThread); 
	} 
 
	// Call ::SetCommState(...) 
	BOOL bRet = ::SetCommState(m_hCommPort, (DCB *) pdcb); 
	if(! bRet) TRACE("Interface::Call SetCommState API failed.\n"); 
 
	// 恢复线程 
	if(m_pReadCommThrd) 
	{ 
		if(m_pReadCommThrd->m_hThread) ::ResumeThread(m_pReadCommThrd->m_hThread); 
	} 
	if(m_pSendCmdThrd) 
	{ 
		if(m_pSendCmdThrd->m_hThread) ::ResumeThread(m_pSendCmdThrd->m_hThread); 
	} 
 
	return bRet; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 获取串口参数信息 
// 参数说明: 传入一个DCB的指针 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 10:19:58 AM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::GetCommState(const DCB *pdcb) const 
{ 
	ASSERT(m_nCommMode == INTERFACE_COMMPORT); 
	ASSERT(m_hCommPort != NULL); 
	if(m_nCommMode != INTERFACE_COMMPORT) return FALSE; 
	if(m_hCommPort == NULL) return FALSE; 
 
	// Call ::GetCommState(...) and return 
	BOOL bRet = ::GetCommState(m_hCommPort, (DCB *) pdcb); 
	if(! bRet) TRACE("Interface::Call GetCommState API failed.\n"); 
 
	return bRet; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 设置串口超时参数 
// 参数说明: COMMTIMEOUTS 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 11:19:11 AM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::SetCommTimeouts(const COMMTIMEOUTS *ptmo) const 
{ 
	ASSERT(m_nCommMode == INTERFACE_COMMPORT); 
	ASSERT(m_hCommPort != NULL); 
	ASSERT(ptmo != NULL); 
	if(m_nCommMode != INTERFACE_COMMPORT) return FALSE; 
	if(m_hCommPort == NULL) return FALSE; 
	if(ptmo == NULL) return FALSE; 
 
	// 暂停线程 
	if(m_pReadCommThrd) 
	{ 
		if(m_pReadCommThrd->m_hThread) ::SuspendThread(m_pReadCommThrd->m_hThread); 
	} 
	if(m_pSendCmdThrd) 
	{ 
		if(m_pSendCmdThrd->m_hThread) ::SuspendThread(m_pSendCmdThrd->m_hThread); 
	} 
 
	// Call ::SetCommTimeouts(...) 
	BOOL bRet = ::SetCommTimeouts(m_hCommPort, (COMMTIMEOUTS *) ptmo); 
	if(! bRet) TRACE("Interface::Call SetCommTimeouts API failed.\n"); 
 
	// 恢复线程 
	if(m_pReadCommThrd) 
	{ 
		if(m_pReadCommThrd->m_hThread) ::ResumeThread(m_pReadCommThrd->m_hThread); 
	} 
	if(m_pSendCmdThrd) 
	{ 
		if(m_pSendCmdThrd->m_hThread) ::ResumeThread(m_pSendCmdThrd->m_hThread); 
	} 
 
	return bRet; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 获取串口超时参数 
// 参数说明: 传入一个COMMTIMEOUTS指针 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 11:25:52 AM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::GetCommTimeouts(const COMMTIMEOUTS *ptmo) const 
{ 
	ASSERT(m_nCommMode == INTERFACE_COMMPORT); 
	ASSERT(m_hCommPort != NULL); 
	if(m_nCommMode != INTERFACE_COMMPORT) return FALSE; 
	if(m_hCommPort == NULL) return FALSE; 
 
	// Call ::GetCommTimeouts(...) and return 
	BOOL bRet = ::GetCommTimeouts(m_hCommPort, (COMMTIMEOUTS *) ptmo); 
	if(! bRet) TRACE("Interface::Call GetCommTimeouts API failed.\n"); 
 
	return bRet; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: TCP Server模式下, 打开接口的函数 
// 参数说明: 监听端口; 接口打开时的回调函数; 接口关闭时的回调函数; 
//			 接口收到数据时的回调函数; 备用参数; 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 2:26:08 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CreateInterface_TcpServer(unsigned int nListenPort, 
											   const void *pfnInterfaceOpenCallback, 
											   const void *pfnInterfaceCloseCallback, 
											   const void *pfnDataProcCallback, 
											   const void *pParamCallback) 
{ 
	ASSERT(m_nCommMode == INTERFACE_TCPSERVER); 
	if(m_nCommMode != INTERFACE_TCPSERVER) return FALSE; 
 
	// Close the previous Interface 
	CloseInterface(); 
	ASSERT(m_pListenSock == NULL && m_pDataSock == NULL); 
 
	// The Interface Data Proc must be a valid pointer 
	ASSERT(pfnDataProcCallback != NULL); 
 
	// Save the params 
	m_nListenPort = nListenPort; 
	m_pfnInterfaceOpenCallback = (void *) pfnInterfaceOpenCallback; 
	m_pfnInterfaceCloseCallback = (void *) pfnInterfaceCloseCallback; 
	m_pfnDataProcCallback = (void *) pfnDataProcCallback; 
	m_pParamCallback = (void *) pParamCallback; 
 
	// Create listen socket for the Tcp Server 
	m_pListenSock = new CInterfaceListenSocket(this); 
	ASSERT(m_pListenSock != NULL); 
 
	if(! m_pListenSock->Create(nListenPort)) 
	{ 
		TRACE("Interface::Create listen socket failed, error code = %d\n", GetLastError()); 
		delete m_pListenSock; 
		m_pListenSock = NULL; 
		return FALSE; 
	} 
	if(! m_pListenSock->Listen()) 
	{ 
		TRACE("Interface::Socket listen failed, error code = %d\n", GetLastError()); 
		m_pListenSock->Close(); 
		delete m_pListenSock; 
		m_pListenSock = NULL; 
		return FALSE; 
	} 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 关闭接口 (Tcp Server 模式) 
// 参数说明:  
// 返回值:  
// 创建人: DavidHowe;  创建时间: 2003-4-30 4:44:33 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CloseInterface_TcpServer(BOOL bInvokeCallback) 
{ 
	// Terminate send-command thread 
	if(m_pSendCmdThrd) 
	{ 
		::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
		delete m_pSendCmdThrd; 
		m_pSendCmdThrd = NULL; 
	} 
 
	if(m_pListenSock) 
	{ 
		m_pListenSock->Close(); 
		delete m_pListenSock; 
		m_pListenSock = NULL; 
	} 
 
	if(m_pDataSock) 
	{ 
		m_pDataSock->Close(); 
		delete m_pDataSock; 
		m_pDataSock = NULL; 
 
		// Call the Interface-Close callback 
		if(bInvokeCallback && m_pfnInterfaceCloseCallback) 
		{ 
			void (*pfnCallback)(const void*) = 
				(void(*)(const void*))m_pfnInterfaceCloseCallback; 
			pfnCallback(m_pParamCallback); 
		} 
	} 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 处理监听socket的OnAccept(..) 
// 参数说明:  
// 返回值: 处理结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 5:39:50 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::ProcessSocketAccept(void) 
{ 
	ASSERT(m_pListenSock != NULL && m_pDataSock == NULL); 
 
	m_pDataSock = new CInterfaceDataSocket(this); 
	ASSERT(m_pDataSock != NULL); 
 
	if(! m_pListenSock->Accept(*m_pDataSock)) 
	{ 
		TRACE("Interface::Socket accept failed.\n"); 
 
		// Accept failed, delete the data socket we just created above 
		delete m_pDataSock; 
		m_pDataSock = NULL; 
 
		// 
		// Recreate the listen socket and relisten 
		// 
		m_pListenSock->Close(); 
		if(! m_pListenSock->Create(m_nListenPort)) 
		{ 
			TRACE("Interface::Recreate listen socket failed, error code = %d\n", 
                GetLastError()); 
			return FALSE; 
		} 
		if(! m_pListenSock->Listen()) 
			TRACE("Interface::Relisten failed, error code = %d\n", GetLastError()); 
 
		return FALSE; 
	} 
	 
	// liep 2003-11-24 
//DEL 	m_pListenSock->GetSockName(m_csClientIp, m_nClientPort); 
 
	// Delete the listen socket 
	m_pListenSock->Close(); 
	delete m_pListenSock; 
	m_pListenSock = NULL; 
 
	// 
	// Start the send-command thread! 
	// 
	m_pSendCmdThrd = (CInterfaceSendCmdThread *) AfxBeginThread( 
		RUNTIME_CLASS(CInterfaceSendCmdThread), 0, CREATE_SUSPENDED); 
	m_pSendCmdThrd->SetInterfaceHandle(this); 
	::ResumeThread(m_pSendCmdThrd->m_hThread); 
    BOOL bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
        TM_START_SENDCOMMANDLOOP, 0, 0); 
    while (! bRet) 
    { 
        Sleep(0); 
        bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
            TM_START_SENDCOMMANDLOOP, 0, 0); 
    } 
 
    // Call the Interface-Open callback 
    if(m_pfnInterfaceOpenCallback) 
    { 
        void (*pfnCallback)(const void*) = 
            (void(*)(const void*))m_pfnInterfaceOpenCallback; 
        pfnCallback(m_pParamCallback); 
    } 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 处理数据socket的OnReceive(..) 
// 参数说明:  
// 返回值: 处理结果 
// 创建人: DavidHowe;  创建时间: 2003-4-30 10:27:28 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::ProcessSocketReceive(void) const 
{ 
	ASSERT(m_pDataSock != NULL); 
 
	BYTE byBuf[RECVBUF_SIZE]; 
	int nRecvLen = m_pDataSock->Receive(byBuf, RECVBUF_SIZE); 
 
	if(nRecvLen > 0) 
	{ 
		if (m_pfnDataProcCallback) 
        { 
            void (*pfnDataProc)(BYTE [], int, void *) = 
                (void(*)(BYTE [], int, void *)) m_pfnDataProcCallback; 
            pfnDataProc(byBuf, nRecvLen, m_pParamCallback); 
        } 
        else ASSERT(FALSE); 
 
		return TRUE; 
	} 
	else return FALSE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 处理数据socket的OnClose(..) 
// 参数说明:  
// 返回值: 处理结果 
// 创建人: DavidHowe;  创建时间: 2003-5-1 12:19:30 AM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::ProcessSocketClose(void) 
{ 
	ASSERT(m_pDataSock != NULL); 
 
	// Terminate send-command thread 
	if(m_pSendCmdThrd) 
	{ 
		::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
		delete m_pSendCmdThrd; 
		m_pSendCmdThrd = NULL; 
	} 
 
	m_pDataSock->Close(); 
	delete m_pDataSock; 
	m_pDataSock = NULL; 
 
	// Call the Interface-Close callback 
	if(m_pfnInterfaceCloseCallback) 
	{ 
		void (*pfnCallback)(const void*) = 
			(void(*)(const void*))m_pfnInterfaceCloseCallback; 
		pfnCallback(m_pParamCallback); 
	} 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: TCP Client模式下, 打开接口的函数 
// 参数说明: 服务端IP; 服务端监听端口; 接口打开时的回调函数; 接口关闭时的回调函数; 
//			 接口收到数据时的回调函数; 备用参数; 
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-5-1 6:59:38 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::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) 
{ 
	ASSERT(m_nCommMode == INTERFACE_TCPCLIENT); 
	if(m_nCommMode != INTERFACE_TCPCLIENT) return FALSE; 
 
	// Close the previous Interface 
	CloseInterface(); 
	ASSERT(m_pDataSock == NULL); 
 
	// The Interface Data Proc must be a valid pointer 
	ASSERT(pfnDataProcCallback != NULL); 
 
	// Save the params 
	m_csServerIp = csServerIp; 
	m_nListenPort = nListenPort; 
	m_pfnInterfaceOpenCallback = (void *) pfnInterfaceOpenCallback; 
	m_pfnInterfaceCloseCallback = (void *) pfnInterfaceCloseCallback; 
	m_pfnDataProcCallback = (void *) pfnDataProcCallback; 
	m_pParamCallback = (void *) pParamCallback; 
 
	// Create data socket and try to connect server side 
	m_pDataSock = new CInterfaceDataSocket(this); 
	ASSERT(m_pDataSock != NULL); 
	if(! m_pDataSock->Create()) 
	{ 
		TRACE("Interface::Create client socket failed, error code = %d\n", 
            GetLastError()); 
		delete m_pDataSock; 
		m_pDataSock = NULL; 
		return FALSE; 
	} 
 
	m_pDataSock->Connect(m_csServerIp, m_nListenPort); 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 关闭接口 (Tcp Client 模式) 
// 参数说明:  
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-5-1 10:55:33 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CloseInterface_TcpClient(BOOL bInvokeCallback) 
{ 
	// Terminate send-command thread 
	if(m_pSendCmdThrd) 
	{ 
		::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
		delete m_pSendCmdThrd; 
		m_pSendCmdThrd = NULL; 
	} 
 
	if(m_pDataSock) 
	{ 
		m_pDataSock->Close(); 
		delete m_pDataSock; 
		m_pDataSock = NULL; 
 
		// Call the Interface-Close callback 
		if(bInvokeCallback && m_pfnInterfaceCloseCallback) 
		{ 
			void (*pfnCallback)(const void*) = 
				(void(*)(const void*))m_pfnInterfaceCloseCallback; 
			pfnCallback(m_pParamCallback); 
		} 
	} 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 处理数据socket的OnConnect(..) 
// 参数说明:  
// 返回值: 操作结果 
// 创建人: DavidHowe;  创建时间: 2003-5-1 10:57:26 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::ProcessSocketConnect(void) 
{ 
    // 
    // Start the send-command thread! 
    // 
    m_pSendCmdThrd = (CInterfaceSendCmdThread *) AfxBeginThread( 
        RUNTIME_CLASS(CInterfaceSendCmdThread), 0, CREATE_SUSPENDED); 
    m_pSendCmdThrd->SetInterfaceHandle(this); 
    ::ResumeThread(m_pSendCmdThrd->m_hThread); 
    BOOL bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
        TM_START_SENDCOMMANDLOOP, 0, 0); 
    while (! bRet) 
    { 
        Sleep(0); 
        bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
            TM_START_SENDCOMMANDLOOP, 0, 0); 
    } 
     
	// Call the Interface-Open callback 
	if(m_pfnInterfaceOpenCallback) 
	{ 
		void (*pfnCallback)(const void*) = 
			(void(*)(const void*))m_pfnInterfaceOpenCallback; 
		pfnCallback(m_pParamCallback); 
	} 
 
	return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 获取连接的客户端的 IP 和 port. 
// 参数说明:  
// 返回值:  
// 创建人: liep;  创建时间: 2003-11-24 15:55:45;  地点: xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
void CCommInterface::GetSockName(CString& csIP, UINT& nPort) const 
{ 
    m_pDataSock->GetPeerName(csIP, nPort); 
} 
 
//----------------------------------------------------------------------------------- 
// Description: Create udp interface 
// Parameters:  
// Return:  
// Author: David Howe;  Date: 2004-8-12 16:15:41;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CreateInterface_Udp(UINT nPort, 
                                         const void *pfnInterfaceOpenCallback, 
                                         const void *pfnInterfaceCloseCallback, 
                                         const void *pfnDataProcCallback, 
                                         const void *pParamCallback) 
{ 
    // Close prev 
    CloseInterface(); 
    ASSERT(m_pUdpSock == NULL); 
 
    // The Interface Data Proc must be a valid pointer 
	ASSERT(pfnDataProcCallback != NULL); 
     
    // Save the params 
    m_nUdpPort = nPort; 
    m_pfnInterfaceOpenCallback = (void *) pfnInterfaceOpenCallback; 
    m_pfnInterfaceCloseCallback = (void *) pfnInterfaceCloseCallback; 
    m_pfnDataProcCallback = (void *) pfnDataProcCallback; 
	m_pParamCallback = (void *) pParamCallback; 
     
    // Create the udp socket 
    m_pUdpSock = new CInterfaceUdpSocket(this); 
    ASSERT(m_pUdpSock); 
     
    if (! m_pUdpSock->Create(m_nUdpPort, SOCK_DGRAM)) 
    { 
        TRACE("Interface::Create udp socket failed, error code = %d\n", GetLastError()); 
        delete m_pUdpSock; 
        m_pUdpSock = NULL; 
        return FALSE; 
    } 
 
    // 
    // Start the send-command thread! 
    // 
    m_pSendCmdThrd = (CInterfaceSendCmdThread *) AfxBeginThread( 
        RUNTIME_CLASS(CInterfaceSendCmdThread), 0, CREATE_SUSPENDED); 
    m_pSendCmdThrd->SetInterfaceHandle(this); 
    ::ResumeThread(m_pSendCmdThrd->m_hThread); 
    BOOL bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
        TM_START_SENDCOMMANDLOOP, 0, 0); 
    // D.H 2004-8-11 15:59:59 
    // 添加对::PostThreadMessage()的返回判断处理, 以修正在Dll工程中 
    //  使用CCommInterface时不能启动发送数据线程的bug. 
    // {F598F388-14D8-464F-BE35-2CA67E1A978C} 
    while (! bRet) 
    { 
        Sleep(0); 
        bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
            TM_START_SENDCOMMANDLOOP, 0, 0); 
    } 
     
    return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// Description: Close udp interface 
// Parameters:  
// Return:  
// Author: David Howe;  Date: 2004-8-12 16:42:42;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::CloseInterface_Udp(BOOL bInvokeCallback) 
{ 
    // Terminate send-command thread 
    if(m_pSendCmdThrd) 
    { 
        ::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
        delete m_pSendCmdThrd; 
        m_pSendCmdThrd = NULL; 
    } 
     
    if(m_pUdpSock) 
    { 
        m_pUdpSock->Close(); 
        delete m_pUdpSock; 
        m_pUdpSock = NULL; 
         
        // Call the Interface-Close callback 
        if(bInvokeCallback && m_pfnInterfaceCloseCallback) 
        { 
            void (*pfnCallback)(const void*) = 
                (void(*)(const void*))m_pfnInterfaceCloseCallback; 
            pfnCallback(m_pParamCallback); 
        } 
    } 
     
    return TRUE; 
} 
 
//----------------------------------------------------------------------------------- 
// Description: Set target host of udp socket 
// Parameters: lpszTargetHost: new host address 
// Return: previous host address 
// Author: David Howe;  Date: 2004-8-12 17:32:41;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
LPCTSTR CCommInterface::SetUdpTargetHost(LPCTSTR lpszTargetHost) 
{ 
    CString csPrevHost = m_csTargetHost; 
    m_csTargetHost = lpszTargetHost; 
 
    return csPrevHost; 
} 
 
//----------------------------------------------------------------------------------- 
// Description: Set target port of udp socket 
// Parameters:  
// Return:  
// Author: David Howe;  Date: 2004-8-12 17:34:29;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
UINT CCommInterface::SetUdpTargetPort(UINT nTargetPort) 
{ 
    UINT nPrevPort = m_nTargetPort; 
    m_nTargetPort = nTargetPort; 
 
    return nPrevPort; 
} 
 
//----------------------------------------------------------------------------------- 
// Description: 处理Udp socket的数据到达消息 
// Parameters:  
// Return:  
// Author: David Howe;  Date: 2004-8-13 11:10:25;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
BOOL CCommInterface::ProcessUdpSocketReceiveFrom(void) const 
{ 
    ASSERT(m_pUdpSock != NULL); 
 
    BYTE byBuf[RECVBUF_SIZE]; 
    CString csTargetHost = _T(""); 
    UINT nTargetPort = 0; 
    int nRecvLen = m_pUdpSock->ReceiveFrom(byBuf, RECVBUF_SIZE, csTargetHost, nTargetPort); 
 
    if (nRecvLen > 0) 
    { 
        if (m_pfnDataProcCallback) 
        { 
            // 我们需要在返回的数据里面带上接收方位置信息 
            memmove(byBuf + csTargetHost.GetLength() + 1 + sizeof(DWORD), byBuf, nRecvLen); 
            memcpy(byBuf, (LPCTSTR) csTargetHost, csTargetHost.GetLength()); 
            byBuf[csTargetHost.GetLength()] = '\0'; 
            memcpy(&byBuf[csTargetHost.GetLength() + 1], &nTargetPort, sizeof(DWORD)); 
 
            // Call callback function 
            void (*pfnDataProc)(BYTE [], int, void *) = 
                (void(*)(BYTE [], int, void *)) m_pfnDataProcCallback; 
            pfnDataProc(byBuf, nRecvLen + csTargetHost.GetLength() + 1 + sizeof(DWORD), 
                m_pParamCallback); 
        } 
        else ASSERT(FALSE); 
 
        return TRUE; 
    } 
    else return FALSE; 
} 
 
/************************************************************************************* 
** Description: 创建E1通信接口 
** Parameters:  
** Return:  
** Author: lipf;  Date: 2003-12-23 13:53:05;  Location: Office 
** Misc:  
**************************************************************************************/ 
BOOL CCommInterface::CreateInterface_E1(unsigned int nCardID,// E1 Card Num 
                                        unsigned int nSlotID, // E1's Time Slot 
                                        const void *pfnInterfaceOpenCallback, 
                                        const void *pfnInterfaceCloseCallback, 
                                        const void *pfnDataProcCallback, 
                                        const void *pParamCallback) 
{ 
#ifndef C7A43868_D29A_4404_9BFD_698A970F8614 
    return FALSE; 
#else 
    ASSERT(m_nCommMode == INTERFACE_E1); 
    if(m_nCommMode != INTERFACE_E1) return FALSE; 
    // Close previous if open 
    CloseInterface(); 
    ASSERT(m_hE1Handle == NULL); 
    ASSERT(pfnDataProcCallback != NULL); 
    if(nCardID < 1 || nCardID > 4) // nCardID is unsigned int , so it is always > 0 
    { 
        TRACE("Interface::E1 Card ID out of range: %d\n", nCardID); 
        return FALSE; 
    } 
    if(nSlotID <= 0 || nSlotID > 31) 
    { 
        TRACE("Interface::E1 Time Slot ID out of range: %d\n", nSlotID); 
        return FALSE; 
    } 
    // Save the params 
    m_nCardID = nCardID; 
    m_nSlotID = nSlotID; 
    m_pfnInterfaceOpenCallback = (void *) pfnInterfaceOpenCallback; 
    m_pfnInterfaceCloseCallback = (void *) pfnInterfaceCloseCallback; 
    m_pfnDataProcCallback = (void *) pfnDataProcCallback; 
    m_pParamCallback = (void *) pParamCallback; 
    // 
    // (Attempt to) open the E1 Card and Set the Param 
    // 
    CString csE1Card; 
    csE1Card.Format("\\\\.\\CardtDevice%d",nCardID-1); 
    m_hE1Handle = CreateFile(csE1Card,GENERIC_READ|GENERIC_WRITE,0,NULL, 
        OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL); 
    if(m_hE1Handle == INVALID_HANDLE_VALUE) 
    { 
        TRACE("E1SC#%d卡打开失败。",nCardID); 
        m_hE1Handle = NULL; 
        return FALSE; 
    } 
 
    BYTE bChannelIndex = nSlotID-1; // 配置程序配置时隙1, 实际打开0 
    unsigned long wLen; 
    if (!DeviceIoControl(m_hE1Handle,IOCTL_SET_CHANNEL,&bChannelIndex,1,NULL,0,&wLen,NULL)) 
    { 
        TRACE("E1SC#%d卡设置通道%d失败。",nCardID, nSlotID); 
        CloseInterface(); 
        return FALSE; 
    } 
         
    SERIAL_BAUD_RATE BaudRate; 
    BaudRate.BaudRate = 9600; 
    if(!DeviceIoControl(m_hE1Handle, IOCTL_SERIAL_SET_BAUD_RATE, &BaudRate, sizeof(SERIAL_BAUD_RATE),NULL,0,&wLen,NULL)) 
    { 
        TRACE("E1SC#%d卡波特率设置失败。",nCardID); 
        CloseInterface(); 
        return false; 
    } 
 
    SERIAL_LINE_CONTROL slc; 
    slc.WordLength = 8; 
    slc.Parity = NO_PARITY; 
    slc.StopBits = 1; 
    if(!DeviceIoControl(m_hE1Handle, IOCTL_SERIAL_SET_LINE_CONTROL, &slc, sizeof(SERIAL_LINE_CONTROL), NULL,0,&wLen,NULL)) 
         
        //	if(!dsiSetChannelLineControl(hE1[nCard-1],nChl,&dlc)) 
    { 
        TRACE("E1SC#%d卡时隙线控设置失败。",nCardID); 
        CloseInterface(); 
        return FALSE; 
    } 
 
    SERIAL_TIMEOUTS tmout ={0}; 
    tmout.ReadIntervalTimeout=30; 
    tmout.ReadTotalTimeoutConstant=6000; 
    tmout.WriteTotalTimeoutConstant=0; 
     
    if(!DeviceIoControl(m_hE1Handle, IOCTL_SERIAL_SET_TIMEOUTS, &tmout, sizeof(SERIAL_TIMEOUTS), NULL,0,&wLen,NULL)) 
    { 
        TRACE("E1SC#%d卡时隙超时设置失败。",nCardID); 
        CloseInterface(); 
        return FALSE; 
    } 
    // 
    // begin the read E1 thread 
    // 
    m_pReadE1Thrd = AfxBeginThread(ReadE1Thread, this); 
 
    // begin the send cmd thread 
     
    m_pSendCmdThrd = (CInterfaceSendCmdThread *) AfxBeginThread( 
        RUNTIME_CLASS(CInterfaceSendCmdThread), 0, CREATE_SUSPENDED); 
    m_pSendCmdThrd->SetInterfaceHandle(this); 
    ::ResumeThread(m_pSendCmdThrd->m_hThread); 
    BOOL bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
        TM_START_SENDCOMMANDLOOP, 0, 0); 
    while (! bRet) 
    { 
        Sleep(0); 
        bRet = ::PostThreadMessage(m_pSendCmdThrd->m_nThreadID, 
            TM_START_SENDCOMMANDLOOP, 0, 0); 
    } 
     
    // Call the Interface-Open callback 
    if(m_pfnInterfaceOpenCallback) 
    { 
        void (*pfnCallback)(const void*) = 
            (void(*)(const void*))m_pfnInterfaceOpenCallback; 
        pfnCallback(m_pParamCallback); 
    }        
    return TRUE; 
#endif // C7A43868_D29A_4404_9BFD_698A970F8614 
} 
 
/************************************************************************************* 
** Description:  
** Parameters:  
** Return:  
** Author: lipf;  Date: 2003-12-23 15:49:19;  Location:  
** Misc:  
**************************************************************************************/ 
BOOL CCommInterface::CloseInterface_E1(BOOL bInvokeCallback) 
{ 
#ifndef C7A43868_D29A_4404_9BFD_698A970F8614 
    return FALSE; 
#else 
    BOOL bRet = TRUE; 
    if(m_hE1Handle != NULL) 
    { 
        // Terminate read-comm thread 
        ASSERT(m_pReadE1Thrd != NULL); 
        if(m_pReadE1Thrd) 
        { 
            if(m_pReadE1Thrd->m_hThread) 
            { 
                ::TerminateThread(m_pReadE1Thrd->m_hThread, 0); 
                delete m_pReadE1Thrd; 
                m_pReadE1Thrd = NULL; 
            } 
        } 
         
        // Terminate send-command thread 
        ASSERT(m_pSendCmdThrd != NULL); 
        if(m_pSendCmdThrd) 
        { 
            ::TerminateThread(m_pSendCmdThrd->m_hThread, 0); 
            ::CloseHandle(m_pSendCmdThrd->m_olWrite.hEvent); // Prevent handle leak 
            delete m_pSendCmdThrd; 
            m_pSendCmdThrd = NULL; 
        } 
         
        // Close commport 
        ASSERT(m_hE1Handle != NULL); 
        bRet = ::CloseHandle(m_hE1Handle); 
        m_hE1Handle = NULL; 
         
        // Close the event's handle (to prevent a handle leak) 
        ASSERT(m_polReadE1 != NULL); 
        if(m_polReadE1) ::CloseHandle(m_polReadE1->hEvent); 
         
        // Call the Interface-Close callback 
        if(bInvokeCallback && m_pfnInterfaceCloseCallback) 
        { 
            void (*pfnCallback)(const void*) = 
                (void(*)(const void*))m_pfnInterfaceCloseCallback; 
            pfnCallback(m_pParamCallback); 
        } 
        // Have a rest, or the same commport cannot be opened immediately 
        Sleep(50); 
    } 
     
    if(! bRet) TRACE("Interface::Close interface failed.\n"); 
     
    return bRet; 
#endif // C7A43868_D29A_4404_9BFD_698A970F8614 
} 
 
 
 
 
 
//----------------------------------------------------------------------------------- 
/////////////////////////////////////////////////////////// 
// CInterfaceSendCmdThread类的实现代码 
/////////////////////////////////////////////////////////// 
//----------------------------------------------------------------------------------- 
IMPLEMENT_DYNCREATE(CInterfaceSendCmdThread, CWinThread) 
 
CInterfaceSendCmdThread::CInterfaceSendCmdThread() 
{ 
	m_pInfc = NULL; 
} 
 
CInterfaceSendCmdThread::~CInterfaceSendCmdThread() 
{ 
} 
 
BOOL CInterfaceSendCmdThread::InitInstance() 
{ 
	// TODO:  perform and per-thread initialization here 
	return TRUE; 
} 
 
int CInterfaceSendCmdThread::ExitInstance() 
{ 
	// TODO:  perform any per-thread cleanup here 
	 
	return CWinThread::ExitInstance(); 
} 
 
BEGIN_MESSAGE_MAP(CInterfaceSendCmdThread, CWinThread) 
	//{{AFX_MSG_MAP(CInterfaceSendCmdThread) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
	//}}AFX_MSG_MAP 
	ON_THREAD_MESSAGE(TM_START_SENDCOMMANDLOOP, Start_SendCommandLoop) 
	ON_THREAD_MESSAGE(TM_START_LOOP_MODE_0, SendCommandLoop_Mode0) 
	ON_THREAD_MESSAGE(TM_START_LOOP_MODE_1, SendCommandLoop_Mode1) 
    ON_THREAD_MESSAGE(TM_START_LOOP_MODE_3, SendCommandLoop_Mode3) 
    ON_THREAD_MESSAGE(TM_START_LOOP_MODE_4, SendCommandLoop_Mode4) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CInterfaceSendCmdThread message handlers 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 发送命令循环总的入口, 当打开接口后发送此消息激活命令发送 
// 参数说明: 未用 
// 返回值:  
// 创建人: DavidHowe;  创建时间: 2003-4-28 5:10:57 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
LRESULT CInterfaceSendCmdThread::Start_SendCommandLoop(WPARAM wParam, LPARAM lParam) 
{ 
    UNUSED_ALWAYS(wParam); 
    UNUSED_ALWAYS(lParam); 
 
	switch(m_pInfc->GetCommMode()) 
	{ 
	case INTERFACE_COMMPORT: // RS232 
		PostThreadMessage(TM_START_LOOP_MODE_0, 0, 0); 
		break; 
	case INTERFACE_TCPSERVER: // Tcp Server 
		PostThreadMessage(TM_START_LOOP_MODE_1, 0, 0); 
		break; 
	case INTERFACE_TCPCLIENT: // Tcp Client 
		PostThreadMessage(TM_START_LOOP_MODE_2, 0, 0); 
		break; 
    case INTERFACE_E1: 
        PostThreadMessage(TM_START_LOOP_MODE_3, 0, 0); 
        break; 
    case INTERFACE_UDP: 
        PostThreadMessage(TM_START_LOOP_MODE_4, 0, 0); 
        break; 
	default: break; 
	} 
 
    return 0L; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 类型0 (RS232) 的发送循环 
// 参数说明: 未用 
// 返回值:  
// 创建人: DavidHowe;  创建时间: 2003-4-28 5:09:51 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
LRESULT CInterfaceSendCmdThread::SendCommandLoop_Mode0(WPARAM wParam, LPARAM lParam) 
{ 
    UNUSED_ALWAYS(wParam); 
    UNUSED_ALWAYS(lParam); 
     
	ASSERT(m_pInfc != NULL); 
	HANDLE hCommPort = m_pInfc->GetCommPortHandle(); 
	ASSERT(hCommPort != NULL); 
 
	BYTE byBuf[SENDBUF_SIZE]; 
	int nLen = 0; 
	DWORD dwBytesWritten = 0; 
 
	memset(&m_olWrite, 0, sizeof(OVERLAPPED)); 
	m_olWrite.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); 
 
	/////////////////////////////////////////////////////////// 
	// Send-command loop 
	/////////////////////////////////////////////////////////// 
	while(TRUE) 
	{ 
		/////////////////////////////////////////////////////////// 
		// 确定命令队列不是正在被操作时, 才允许取命令操作 
		/////////////////////////////////////////////////////////// 
		::WaitForSingleObject(m_pInfc->m_hEvtCanGetCmdToSend, INFINITE); 
 
		if(m_pInfc->GetCmdToSend(byBuf, nLen)) 
		{ 
			if(! ::WriteFile(hCommPort, byBuf, nLen, &dwBytesWritten, &m_olWrite)) 
			{ 
				if(GetLastError() == ERROR_IO_PENDING) 
				{ 
					if(::GetOverlappedResult(hCommPort, &m_olWrite, &dwBytesWritten, TRUE)) 
						::ResetEvent(m_olWrite.hEvent); 
				} 
			} 
 
			// If sent successfully, delete the command 
			if(dwBytesWritten == (DWORD) nLen) 
			{ 
				if(! m_pInfc->DeleteFirstCmd()) 
					TRACE("Interface::Delete command failed.\n"); 
			} 
			else 
			{ 
				TRACE("Interface::Send data failed.\n"); 
			} 
		} 
 
        /* D.H 2003-11-20 I forgot this before */ 
        ::SetEvent(m_pInfc->m_hEvtCanGetCmdToSend); 
 
		// Sleep for a while before sending next command (if any), 
		//  to let the thread cool down. 
		Sleep(m_pInfc->GetMinIntervalBetweenCmds()); 
	} 
 
    return 0L; 
} 
 
//----------------------------------------------------------------------------------- 
// 函数说明: 类型1 (Tcp Server/Client) 的发送循环 
// 参数说明:  
// 返回值:  
// 创建人: DavidHowe;  创建时间: 2003-4-30 11:35:52 PM;  地点: Xi'an 
// 备注/修改记录:  
//----------------------------------------------------------------------------------- 
LRESULT CInterfaceSendCmdThread::SendCommandLoop_Mode1(WPARAM wParam, LPARAM lParam) 
{ 
    UNUSED_ALWAYS(wParam); 
    UNUSED_ALWAYS(lParam); 
     
	ASSERT(m_pInfc != NULL); 
	CInterfaceDataSocket *pSock = m_pInfc->GetDataSocket(); 
	ASSERT(pSock != NULL); 
 
	BYTE byBuf[SENDBUF_SIZE]; 
	int nLen = 0; 
	DWORD dwBytesWritten = 0; 
 
	/////////////////////////////////////////////////////////// 
	// Send-command loop 
	/////////////////////////////////////////////////////////// 
	while(TRUE) 
	{ 
		/////////////////////////////////////////////////////////// 
		// 确定命令队列不是正在被操作时, 才允许取命令操作 
		/////////////////////////////////////////////////////////// 
		::WaitForSingleObject(m_pInfc->m_hEvtCanGetCmdToSend, INFINITE); 
 
        // D.H 2004-6-21 11:15:18 
        // 发现一个可能造成发送失败的问题, 我应该在OnSend()里面利用 
        //  事件来判断是否能够发送数据, 以避免socket阻塞. 
        // {A4F90344-73F1-48fa-8D18-760C1846B9EF} 
		if(m_pInfc->GetCmdToSend(byBuf, nLen)) 
		{ 
            // D.H 2004-6-21 11:39:25 
            // Wait for the event, untill we can send data. 
            ::WaitForSingleObject(pSock->GetEvtHandle_SocketCanSend(), 500/* ms */); 
 
			// Send data out 
			// David 2003-5-2 1:08:26 AM 
			dwBytesWritten = pSock->Send(byBuf, nLen); 
             
			// If sent successfully, delete the command 
			if(dwBytesWritten != SOCKET_ERROR) 
			{ 
                if (dwBytesWritten != (DWORD) nLen) // 发送长度不对 
                { 
                    TRACE("Interface(TCP/IP)::Send %d bytes, while wanna send %d bytes.\n", 
                        dwBytesWritten, nLen); 
                } 
				if(! m_pInfc->DeleteFirstCmd()) 
                { 
					TRACE("Interface(TCP/IP)::Delete sent-out command failed.\n"); 
                } 
 
                // If sent successfully, set the event so that we can send next packet. 
                ::SetEvent(pSock->GetEvtHandle_SocketCanSend()); 
			} 
			else // error sending! 
			{ 
				TRACE("Interface(TCP/IP)::Sends data failed, GetLastError()=%d.\n", 
                    GetLastError()); 
            } 
		} 
         
        /* D.H 2003-11-20 I forgot this before */ 
        ::SetEvent(m_pInfc->m_hEvtCanGetCmdToSend); 
 
		// Sleep for a while before sending next command (if any), 
		//  to let the thread cool down. 
		Sleep(m_pInfc->GetMinIntervalBetweenCmds()); 
	} 
 
    return 0L; 
} 
 
/************************************************************************************* 
** Description: E1发送数据 
** Parameters:  
** Return:  
** Author: lipf;  Date: 2003-12-23 15:42:46;  Location: Office 
** Misc:  
**************************************************************************************/ 
LRESULT CInterfaceSendCmdThread::SendCommandLoop_Mode3(WPARAM wParam, LPARAM lParam) 
{ 
#ifndef C7A43868_D29A_4404_9BFD_698A970F8614 
    return 0L; 
#else 
    UNUSED_ALWAYS(wParam); 
    UNUSED_ALWAYS(lParam); 
     
    ASSERT(m_pInfc != NULL); 
    HANDLE hE1 = m_pInfc->GetE1Handle(); 
    ASSERT(hE1 != NULL); 
     
    BYTE byBuf[SENDBUF_SIZE]; 
    int nLen = 0; 
    DWORD dwBytesWritten = 0; 
     
    memset(&m_olWrite, 0, sizeof(OVERLAPPED)); 
    m_olWrite.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); 
     
    /////////////////////////////////////////////////////////// 
    // Send-command loop 
    /////////////////////////////////////////////////////////// 
    while(TRUE) 
    { 
        /////////////////////////////////////////////////////////// 
        // 确定命令队列不是正在被操作时, 才允许取命令操作 
        /////////////////////////////////////////////////////////// 
        ::WaitForSingleObject(m_pInfc->m_hEvtCanGetCmdToSend, INFINITE); 
         
        if(m_pInfc->GetCmdToSend(byBuf, nLen)) 
        { 
            if(! ::WriteFile(hE1, byBuf, nLen, &dwBytesWritten, &m_olWrite)) 
            { 
                if(GetLastError() == ERROR_IO_PENDING) 
                { 
                    if(::GetOverlappedResult(hE1, &m_olWrite, &dwBytesWritten, TRUE)) 
                        ::ResetEvent(m_olWrite.hEvent); 
                } 
            } 
             
            // If sent successfully, delete the command 
            if(dwBytesWritten == (DWORD) nLen) 
            { 
                if(! m_pInfc->DeleteFirstCmd()) 
                    TRACE("Interface::Delete command failed.\n"); 
            } 
            else 
            { 
                TRACE("Interface::Send data failed.\n"); 
            } 
        } 
 
        /* D.H 2003-11-20 I forgot this before */ 
        ::SetEvent(m_pInfc->m_hEvtCanGetCmdToSend); 
         
        // Sleep for a while before sending next command (if any), 
        //  to let the thread cool down. 
        Sleep(m_pInfc->GetMinIntervalBetweenCmds()); 
    } 
 
    return 0L; 
#endif // C7A43868_D29A_4404_9BFD_698A970F8614 
} 
 
//----------------------------------------------------------------------------------- 
// Description: Udp发送数据 
// Parameters:  
// Return:  
// Author: David Howe;  Date: 2004-8-12 16:20:36;  Location: Office 
// Misc:  
//----------------------------------------------------------------------------------- 
LRESULT CInterfaceSendCmdThread::SendCommandLoop_Mode4(WPARAM wParam, LPARAM lParam) 
{ 
    UNUSED_ALWAYS(wParam); 
    UNUSED_ALWAYS(lParam); 
 
    ASSERT(m_pInfc != NULL); 
    CInterfaceUdpSocket *pUdpSock = m_pInfc->GetUdpSocket(); 
    ASSERT(pUdpSock != NULL); 
 
    BYTE byBuf[SENDBUF_SIZE]; 
    int nLen = 0; 
    DWORD dwBytesWritten = 0; 
 
    //////////////////////////////////////////////////////////// 
    // Send command loop 
    //////////////////////////////////////////////////////////// 
    while (TRUE) 
    { 
        /////////////////////////////////////////////////////////// 
        // 确定命令队列不是正在被操作时, 才允许取命令操作 
        /////////////////////////////////////////////////////////// 
		::WaitForSingleObject(m_pInfc->m_hEvtCanGetCmdToSend, INFINITE); 
 
        if (m_pInfc->GetCmdToSend(byBuf, nLen)) 
        { 
            // 从byBuf中解析发送的目的信息 
            CString csTargetHost; 
            UINT nTargetPort = 0; 
            csTargetHost.Format("%s", byBuf); 
            memcpy(&nTargetPort, &byBuf[csTargetHost.GetLength() + 1], sizeof(DWORD)); 
 
            // Send data out 
            dwBytesWritten = pUdpSock->SendTo(byBuf + csTargetHost.GetLength() + 1 + 
                sizeof(DWORD), nLen - csTargetHost.GetLength() - 1 - sizeof(DWORD), 
                nTargetPort, csTargetHost.IsEmpty() ? NULL : (LPCTSTR) csTargetHost); 
 
            // If sent successfully, delete the command 
            if(dwBytesWritten != SOCKET_ERROR) 
            { 
                if (dwBytesWritten !=  
                    (DWORD) nLen - csTargetHost.GetLength() - 1 - sizeof(DWORD)) // 发送长度不对 
                { 
                    TRACE("Interface(UDP)::Send %d bytes, while wanna send %d bytes.\n", 
                        dwBytesWritten, nLen - csTargetHost.GetLength() - 1 - sizeof(DWORD)); 
                } 
                if(! m_pInfc->DeleteFirstCmd()) 
                { 
                    TRACE("Interface(UDP)::Delete sent-out command failed.\n"); 
                } 
            } 
            else // error sending! 
            { 
                TRACE("Interface(UDP)::Sends data failed, GetLastError()=%d.\n", 
                    GetLastError()); 
            } 
        } 
 
        ::SetEvent(m_pInfc->m_hEvtCanGetCmdToSend); 
 
        Sleep(m_pInfc->GetMinIntervalBetweenCmds()); 
    } 
 
    return 0L; 
} 
 
 
 
 
 
 
 
 
//----------------------------------------------------------------------------------- 
//----------------------------------------------------------------------------------- 
///////////////////////////////////////////////////////////////////////////// 
// CInterfaceListenSocket类的实现代码 
/////////////////////////////////////////////////////////// 
//----------------------------------------------------------------------------------- 
 
CInterfaceListenSocket::CInterfaceListenSocket() 
{ 
    // Call another constructor 
    ASSERT(FALSE); 
} 
 
CInterfaceListenSocket::CInterfaceListenSocket(CCommInterface *pInfc) 
{ 
	ASSERT(pInfc != NULL); 
	m_pInfc = pInfc; 
} 
 
CInterfaceListenSocket::~CInterfaceListenSocket() 
{ 
} 
 
// Do not edit the following lines, which are needed by ClassWizard. 
#if 0 
BEGIN_MESSAGE_MAP(CInterfaceListenSocket, CAsyncSocket) 
	//{{AFX_MSG_MAP(CInterfaceListenSocket) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
#endif	// 0 
 
///////////////////////////////////////////////////////////////////////////// 
// CInterfaceListenSocket member functions 
 
void CInterfaceListenSocket::OnAccept(int nErrorCode)  
{ 
	if(! nErrorCode) 
	{ 
		m_pInfc->ProcessSocketAccept(); 
	} 
 
	CAsyncSocket::OnAccept(nErrorCode); 
} 
 
 
 
 
 
 
 
 
//----------------------------------------------------------------------------------- 
//----------------------------------------------------------------------------------- 
/////////////////////////////////////////////////////////// 
// CInterfaceDataSocket类的实现代码 
/////////////////////////////////////////////////////////// 
//----------------------------------------------------------------------------------- 
 
CInterfaceDataSocket::CInterfaceDataSocket() 
{ 
    // Do not call this, call another constructor 
    ASSERT(FALSE); 
} 
 
CInterfaceDataSocket::CInterfaceDataSocket(CCommInterface *pInfc) 
{ 
	ASSERT(pInfc != NULL); 
	m_pInfc = pInfc; 
 
    // D.H 2004-6-21 11:25:53 
    // Init event 
    m_hEvtSocketCanSend = ::CreateEvent(NULL, FALSE, FALSE, NULL); 
} 
 
CInterfaceDataSocket::~CInterfaceDataSocket() 
{ 
    ::CloseHandle(m_hEvtSocketCanSend); 
} 
 
 
// Do not edit the following lines, which are needed by ClassWizard. 
#if 0 
BEGIN_MESSAGE_MAP(CInterfaceDataSocket, CAsyncSocket) 
	//{{AFX_MSG_MAP(CInterfaceDataSocket) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
#endif	// 0 
 
void CInterfaceDataSocket::OnReceive(int nErrorCode)  
{ 
	if(! nErrorCode) 
	{ 
		m_pInfc->ProcessSocketReceive(); 
	} 
 
	CAsyncSocket::OnReceive(nErrorCode); 
} 
 
void CInterfaceDataSocket::OnConnect(int nErrorCode)  
{ 
	if(! nErrorCode || nErrorCode == WSAEISCONN) 
	{ 
		m_pInfc->ProcessSocketConnect(); 
	} 
	 
	CAsyncSocket::OnConnect(nErrorCode); 
} 
 
void CInterfaceDataSocket::OnClose(int nErrorCode)  
{ 
	m_pInfc->ProcessSocketClose(); 
 
	CAsyncSocket::OnClose(nErrorCode); 
} 
 
// D.H 2004-6-21 11:32:58 
// To know when I could send data with a Send() call. 
void CInterfaceDataSocket::OnSend(int nErrorCode) 
{ 
    // 事件置信号态, 允许发送线程发送 
    SetEvent(m_hEvtSocketCanSend); 
 
    CAsyncSocket::OnSend(nErrorCode); 
} 
 
 
 
 
 
 
//------------------------------------------------------------------------------------- 
//////////////////////////////////////////////////////////// 
// D.H 2004-8-12 
// CInterfaceUdpSocket类的实现代码 
//////////////////////////////////////////////////////////// 
 
CInterfaceUdpSocket::CInterfaceUdpSocket() 
{ 
    // Do not call this, call another constructor 
    ASSERT(FALSE); 
} 
 
CInterfaceUdpSocket::CInterfaceUdpSocket(CCommInterface *pInfc) 
{ 
    ASSERT(pInfc != NULL); 
    m_pInfc = pInfc; 
} 
 
CInterfaceUdpSocket::~CInterfaceUdpSocket() 
{ 
} 
 
//////////////////////////////////////////////////////////// 
// Do not edit the following lines, which are needed by ClassWizard. 
#if 0 
    BEGIN_MESSAGE_MAP(CInterfaceUdpSocket, CAsyncSocket) 
    //{{AFX_MSG_MAP(CInterfaceUdpSocket) 
    //}}AFX_MSG_MAP 
    END_MESSAGE_MAP() 
#endif	// 0 
 
void CInterfaceUdpSocket::OnReceive(int nErrorCode)  
{ 
    if(! nErrorCode) 
    { 
        m_pInfc->ProcessUdpSocketReceiveFrom(); 
    } 
     
    CAsyncSocket::OnReceive(nErrorCode); 
} 
 
 
//----------------------------------------------------------------------------------- 
// End of file