⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpclient_ce.cpp

📁 Windows CE下的客户端TCP/IP程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// TCPClient_CE.cpp: implementation of the CTCPClient_CE class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TcpClient_mod.h"
#include "TCPClient_CE.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
extern CTcpClient_modApp	theApp;

#define MAX_TIMEOUT	60
#define SENDQUEUE	1
#define RECVQUEUE	2

DWORD WINAPI SocketWriteThread(LPVOID lParam);
    //通讯线程函数
DWORD WINAPI SocketThreadFunc(LPVOID lparam);

//构造函数
CTCPClient_CE::CTCPClient_CE(LPCTSTR szIPaddr, UINT nPort, UINT nBuffMax, HWND hWnd, 
                             LPCTSTR initStr, UINT ninitLen)
{
    //初始化socket环境
    WSADATA wsd;
    WSAStartup(MAKEWORD(1,1),&wsd);
    //创建线程退出事件句柄
    m_exitThreadEvent = CreateEvent(NULL,FALSE,FALSE,NULL); 
	m_exitWriteEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
    
    m_remoteHost = szIPaddr;
    m_port = nPort;
    m_nbuffMax = nBuffMax;
    m_hwnd = hWnd;
    memset(m_initStr, 0, 1024);
    memcpy(m_initStr, initStr, ninitLen);
    m_ninitLen = ninitLen;

    m_socket = INVALID_SOCKET; //初始化置m_socket为INVALID
    m_tcpThreadHandle = INVALID_HANDLE_VALUE;
	m_tcpWriteHandle =INVALID_HANDLE_VALUE;

	m_bDead = true;
	m_nTimeout = 0;
}

//析构函数
CTCPClient_CE::~CTCPClient_CE()
{
    //释放socket资源
    WSACleanup();
    //关闭线程退出事件句柄
    CloseHandle(m_exitThreadEvent);
	CloseHandle(m_exitWriteEvent);

	if (m_tcpThreadHandle != INVALID_HANDLE_VALUE) 
		CloseHandle(m_tcpThreadHandle);
	if (m_tcpWriteHandle != INVALID_HANDLE_VALUE) 
		CloseHandle(m_exitWriteEvent);
    
    OutputDebugString(_T("Deconstructing CTcpClient_CE\n"));
}
/*
 *	SOCKET的写线程
 */
DWORD WINAPI SocketWriteThread(LPVOID lParam)
{
    CTCPClient_CE *pClient;
    //得到CTCPClient_CE实例指针
    pClient = (CTCPClient_CE*)lParam;

    // 发送给父窗口的错误指示消息
    static CString	msg; // 静态变量的原因是由于PostMessage是立刻返回的,因此lParam必须是
						// 内存持久的,所以必须为static
	DWORD	dwRet;

	while (TRUE)
	{
		//收到退出事件,结束线程
		dwRet = WaitForSingleObject(pClient->m_exitWriteEvent,0);
        if (dwRet == WAIT_OBJECT_0)
        {
            break;
        }
		else if (dwRet == WAIT_FAILED)
		{
			break;
		}
		// 查询发送缓冲区是否有数据,如果有则发送
		if (!pClient->IsQueueEmpty(SENDQUEUE)) 
		{
			char	sendbuf[1024];
			int		sendlen = 0;
			bool	bRet = false;
			while (pClient->GetSendBuff(sendbuf,&sendlen))
			{
				bRet = pClient->SendData(sendbuf,sendlen);
				if (!bRet)
				{ // 发送失败
					break;
				}
				pClient->m_nTimeout = 0;	// 链路正常
			}
			
			if (!bRet)
			{ // 发送失败				
				//关闭客户端socket
				pClient->SelfClose();
				//pClient->Close();
				
				msg = pClient->GetErrorString();
				::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR
					,(LPARAM)msg.GetBuffer(0));
				break;
			}
		}
		Sleep(100);
	}

	OutputDebugString(_T("Quit SocketWriteThread Function\n"));
	return 0;
}

/*--------------------------------------------------------------------
【函数介绍】:  此线程用于监听TCP客户端通讯的事件,例如当接收到数据、
连接断开和通讯过程发生错误等事件
【入口参数】:  lparam:无类型指针,可以通过此参数,向线程中传入需要用到的资源。
在这里我们将CTCPClient_CE类实例指针传进来
【出口参数】:  (无)
【返回  值】:  返回值没有特别的意义,在此我们将返回值设为0。
---------------------------------------------------------------------*/
DWORD WINAPI SocketThreadFunc(LPVOID lparam)
{
    CTCPClient_CE *pClient;
    //得到CTCPClient_CE实例指针
    pClient = (CTCPClient_CE*)lparam;
    //定义读事件集合
    fd_set fdRead;
    int ret;
    //定义事件等待时间
    TIMEVAL	aTime;
    aTime.tv_sec = 1;
    aTime.tv_usec = 0;
    
    // 发送给父窗口的错误指示消息
    static CString	msg; // 静态变量的原因是由于PostMessage是立刻返回的,因此lParam必须是
						// 内存持久的,所以必须为static
	DWORD	dwRet = 0;
			
    
    if (!pClient->Connect())
    {	
	//如果连接失败,关闭SOCKET,准备等待modTcp_end结束此对象
        //pClient->Close();
		pClient->SelfClose();

		msg = pClient->GetErrorString();
        ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR,(LPARAM)msg.GetBuffer(0));

		// 连接失败,报告错误后,直接退出该线程
		OutputDebugString(_T("Quit SocketThreadFunc Function\n"));
		return 0;
	}
	else
	{ // 连接成功
		::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_SUCCESS,0);
	}
    
	// 启动SOCKET的写线程
	if (!pClient->BeginWriteThread())
	{
		pClient->SelfClose();
		msg = pClient->GetErrorString();
        ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR,(LPARAM)msg.GetBuffer(0));
		OutputDebugString(_T("Quit SocketThreadFunc Function\n"));
		return 0;
	}
	
    while (TRUE)
    {
        //收到退出事件,结束线程
		dwRet = WaitForSingleObject(pClient->m_exitThreadEvent,0);
        if (dwRet == WAIT_OBJECT_0)
        {
            break;
        }
		else if (dwRet == WAIT_FAILED)
		{
			OutputDebugString(_T("Tcpclient has been destructed\n"));
			break;
		}
		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
        //监听socket来的数据
        FD_ZERO(&fdRead);
        //给客户端socket设置读事件
        FD_SET(pClient->m_socket,&fdRead);
        //调用select函数,判断是否有读事件发生
        ret = select(0,&fdRead,NULL,NULL,&aTime);
        
        if (ret == SOCKET_ERROR)
        {
            //关闭客户端socket
			pClient->SelfClose();
			
			msg = pClient->GetErrorString();
            ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR,(LPARAM)msg.GetBuffer(0));
			//pClient->Close();
            break;
        }
        
        
        if (ret > 0)
        {
            if (FD_ISSET(pClient->m_socket,&fdRead))
            {
                //发生读事件
                char recvBuf[1024];//, rBuffer[512];
                int recvLen;
                ZeroMemory(recvBuf,1024);
                //接收数据
                recvLen = recv(pClient->m_socket,recvBuf, 1024,0); //1024
//				recvLen = 0;
//				do {
//					nRead = recv(pClient->m_socket,rBuffer, 512,0);
//					recvLen += nRead;
//					memcpy(recvBuf+recvLen,rBuffer,nRead);
//					memset(rBuffer,0,512);
//				} while(recvLen<512 && nRead>0);
				
				// handle error
                if (recvLen == SOCKET_ERROR)
                {
                  //关闭客户端socket
                  //pClient->Close();
					pClient->SelfClose();
					
                    //触发socket错误事件
					msg = pClient->GetErrorString();
                    ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR,(LPARAM)msg.GetBuffer(0));
                    
                    break;
                }
                else if (recvLen == 0)
                {
                    //触发与服务器端断开事件
                    //关闭客户端socket
					pClient->SelfClose();
					// pClient->Close();
                    msg = _T("服务器已经关闭连接");
                    ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_DISCONNECT,(LPARAM)msg.GetBuffer(0));
                    
                    break;
                }
                else
                {
                    //将接收的数据放入缓冲池内
                    pClient->AddBuff(recvBuf, recvLen);

					pClient->m_nTimeout = 0;	// 链路正常
                    
                    ::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP, TCP_DATA_RECV, NULL);
                }
            }// end if (FD_ISSET...)
        }// end if (ret > 0) 
        
        if (ret == 0) 
        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -