📄 tcpclient_ce.cpp
字号:
pClient->m_nTimeout++; // 对超时的情况进行累加,超过MAX_TIMEOUT次,则表示链路已经无效
if (pClient->m_nTimeout >= MAX_TIMEOUT)
{
pClient->SelfClose();
// pClient->Close();
msg.Format(_T("超时,断开服务器"));
::PostMessage(pClient->m_hwnd,WM_USER_GPS_TCP,TCP_ERROR,(LPARAM)msg.GetBuffer(0));
break;
}
}
}// end while(TRUE)
OutputDebugString(_T("Quit SocketThreadFunc Function\n"));
return 0;
}
/*--------------------------------------------------------------------
【函数介绍】: 分配缓冲池,打开客户端socket,并启动客户端线程
【出口参数】: (无)
【返回 值】: TRUE:打开成功;FALSE:打开失败
说明:该函数用在modTCP_init,是用户线程调用的,所以如果调用失败,应该自动删除对象
---------------------------------------------------------------------*/
bool CTCPClient_CE::Open()
{
//分配缓冲池,其中发送缓冲设置为10个缓冲块
if (!m_buffqueue.AllocateBuff(m_nbuffMax))
{
return false;
}
if (!m_sendQueue.AllocateBuff(10))
{
return false;
}
//复位线程退出事件
ResetEvent(m_exitThreadEvent);
//创建TCP套接字
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (m_socket == SOCKET_ERROR)
{
return FALSE;
}
//创建通讯线程
m_tcpThreadHandle = CreateThread(NULL,0,SocketThreadFunc,this,0,NULL);
if (m_tcpThreadHandle == INVALID_HANDLE_VALUE)
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
return FALSE;
}
return TRUE;
}
/*--------------------------------------------------------------------
【函数介绍】: 用于主线程关闭客户端socket线程
【入口参数】: (无)
【出口参数】: (无)
【返回 值】: TRUE:关闭成功;FALSE:关闭失败
---------------------------------------------------------------------*/
bool CTCPClient_CE::Close()
{
//发送通讯线程结束事件
SetEvent(m_exitThreadEvent); // 设置线程退出信号
SetEvent(m_exitWriteEvent);
//关闭Socket,释放资源
OutputDebugString(_T("Begin closesocket\n"));
if (m_socket!=INVALID_SOCKET)
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
OutputDebugString(_T("Begin Wait m_tcpThreadHandle\n"));
DWORD dwRet = WaitForSingleObject(m_tcpThreadHandle,INFINITE);
if (dwRet == WAIT_OBJECT_0)
{
CloseHandle(m_tcpThreadHandle);
m_tcpThreadHandle = INVALID_HANDLE_VALUE;
}
OutputDebugString(_T("Begin Wait m_tcpWriteHandle\n"));
dwRet =WaitForSingleObject(m_tcpWriteHandle,INFINITE);
if (dwRet == WAIT_OBJECT_0)
{
CloseHandle(m_tcpWriteHandle);
m_tcpWriteHandle = INVALID_HANDLE_VALUE;
}
OutputDebugString(_T("TCP OK\n"));
return TRUE;
}
/*--------------------------------------------------------------------
【函数介绍】: 用于建立与TCP服务器连接
【入口参数】: (无)
【出口参数】: (无)
【返回 值】: TRUE:建立连接成功;FALSE:建立连接失败
---------------------------------------------------------------------*/
bool CTCPClient_CE::Connect()
{
struct sockaddr_in addr;
int err;
addr.sin_family = AF_INET;
addr.sin_port = htons(m_port);
//此处要将双字节转换成单字节
char ansiRemoteHost[255];
ZeroMemory(ansiRemoteHost,255);
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,m_remoteHost,wcslen(m_remoteHost)
,ansiRemoteHost,wcslen(m_remoteHost),NULL,NULL);
addr.sin_addr.s_addr=inet_addr(ansiRemoteHost);
//此时采用同步连接方式,connect直接返回成功或是失败
err = connect(m_socket,(struct sockaddr *)&addr,sizeof(addr));
CString _err;
if (err == 0)
{
_err.Format(_T("connect %s:%d success\n"),m_remoteHost,m_port);
OutputDebugString(_err);
//设置通讯模式为异步模式
DWORD ul= 1;
ioctlsocket(m_socket,FIONBIO,&ul);
return TRUE;
}
return FALSE;
}
/*--------------------------------------------------------------------
【函数介绍】: 向服务器端发送数据
【入口参数】: buf:待发送的数据
len:待发送的数据长度
【出口参数】: (无)
【返回 值】: TRUE:发送数据成功;FALSE:发送数据失败
---------------------------------------------------------------------*/
bool CTCPClient_CE::SendData(const char * buf , int len)
{
int nBytes = 0;
int nSendBytes=0;
int nCount = 0;
DWORD dwError;
while (nSendBytes < len)
{
nBytes = send(m_socket,buf+nSendBytes,len-nSendBytes,0);
if (nBytes==SOCKET_ERROR )
{
dwError = WSAGetLastError();
if (dwError == WSAEWOULDBLOCK)
{
nBytes = 0;
if (nCount++ > 5)
{
WSASetLastError(WSAETIMEDOUT);
return FALSE;
}
}
else
{
WSASetLastError(dwError);
return FALSE;
}
}
nSendBytes = nSendBytes + nBytes;
if (nSendBytes < len)
{
Sleep(100);
}
}
return TRUE;
}
/*
* 从缓冲池中取出一个缓冲块,存放数据
* 返回值:true 正确的存放了数据
* false 缓冲池没有空闲空间
*/
bool CTCPClient_CE::AddBuff(const char *buf, int len)
{
return m_buffqueue.AddData(buf,len);
}
/*
* 取出数据,并把数据原占用的缓冲块加入缓冲池内
* 返回值:true 成功取得数据
* false 缓冲区内没有数据
*/
bool CTCPClient_CE::GetBuff(char *buf, int *plen)
{
return m_buffqueue.GetData(buf,plen);
}
bool CTCPClient_CE::AddSendQueue(const char *buf, int len)
{
return m_sendQueue.AddData(buf,len);
}
bool CTCPClient_CE::GetSendBuff(char *buf, int *plen)
{
return m_sendQueue.GetData(buf,plen);
}
BOOL CTCPClient_CE::IsQueueEmpty(UINT nTag)
{
if (nTag == SENDQUEUE)
return m_sendQueue.IsEmpty();
if (nTag == RECVQUEUE)
return m_buffqueue.IsEmpty();
return TRUE;
}
/*
* CTCPClient_CE的生命周期伴随着SOCKET连接开始而开始,断开而结束。
* 因此,m_bDead主要用来标识由于远程主机因素导致连接断开情况
*/
bool CTCPClient_CE::IsDead()
{
return m_bDead;
}
void CTCPClient_CE::SelfClose()
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
m_bDead = true;
}
/*
* 由SocketThreadFunc产生写线程
*/
bool CTCPClient_CE::BeginWriteThread()
{
ResetEvent(m_exitWriteEvent);
m_tcpWriteHandle = CreateThread(NULL,0,SocketWriteThread,this,0,NULL);
if (m_tcpThreadHandle == INVALID_HANDLE_VALUE)
return false;
return true;
}
LPCTSTR CTCPClient_CE::GetErrorString()
{
static wchar_t msg[128];
DWORD code = WSAGetLastError();
switch(code)
{
case 10060:
wcscpy(msg,_T("\n原因:连接基站服务器超时!"));
break;
case 10061:
wcscpy(msg,_T("\n原因:基站服务器软件可能未启动!"));
break;
case 10065:
wcscpy(msg,_T("\n原因:可能未打开GPRS!"));
break;
case 10054:
wcscpy(msg,_T("\n原因:连接被强制关闭!"));
break;
default:
wcscpy(msg,_T("\n原因:请检查或重试!"));
break;
}
return (LPCTSTR)msg;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -