📄 tcpclient_ce.cpp
字号:
// 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 + -