884 lines
20 KiB
C++
884 lines
20 KiB
C++
// QQTX.cpp: implementation of the CQQTX class.
|
||
//
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#include "stdafx.h"
|
||
#include "QQTX.h"
|
||
|
||
|
||
/*
|
||
#ifdef _DEBUG
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[]=__FILE__;
|
||
#define new DEBUG_NEW
|
||
#endif
|
||
*/
|
||
//////////////////////////////////////////////////////////////////////
|
||
// Construction/Destruction
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include "..\..\..\public\md53\\md5_L.h"
|
||
|
||
|
||
CQQTX::CQQTX()
|
||
{
|
||
m_hSocket = INVALID_SOCKET;
|
||
memset( m_szIP , 0 , sizeof(m_szIP) );
|
||
m_lPort = 0;
|
||
m_bQuitThread = false;
|
||
m_dwEndSendTime = 0;
|
||
m_dwEndRecvTime = 0;
|
||
m_dwTestCount = 0;
|
||
m_bRecvFrame = false;
|
||
|
||
m_lID = 1;
|
||
m_pRecvProc = NULL;
|
||
m_bConnect = false;
|
||
m_bLoginQQTX= -1;
|
||
m_bInitQQTX = false;
|
||
|
||
memset(m_szQQTXIP ,0,sizeof(m_szQQTXIP));
|
||
memset(m_szQQTXUser ,0,sizeof(m_szQQTXUser));
|
||
memset(m_szQQTXPasswd,0,sizeof(m_szQQTXPasswd));
|
||
memset(m_szQQTXKey ,0,sizeof(m_szQQTXKey));
|
||
m_lConnectType = 2; //默认是接收与发送类型
|
||
|
||
WSADATA wsaData; //用于初始化socket的结构
|
||
//以下为初始化SOCKET环境
|
||
int iTemp=WSAStartup(0x0101,&wsaData); //初始化socket环境
|
||
|
||
InitializeCriticalSection(&m_CriDeliverList);
|
||
InitializeCriticalSection(&m_CriErrMsg);
|
||
InitializeCriticalSection(&m_CriSendFrame);
|
||
|
||
|
||
|
||
|
||
//定义队列
|
||
m_lSendID = 1;
|
||
m_pDeliverList = new QQTX_Deliver_List[QQTX_MAX_DELIVER];
|
||
m_lDeliverList=0;
|
||
for ( int i=0 ; i<QQTX_MAX_DELIVER ; i++ )
|
||
{
|
||
m_pDeliverList[i].lSendID = 0;
|
||
}
|
||
|
||
m_dwEndSocketSendTime = 0;
|
||
m_lSendInterval = 0;
|
||
|
||
m_hThread = INVALID_HANDLE_VALUE;
|
||
m_hThread_Send = INVALID_HANDLE_VALUE;
|
||
}
|
||
|
||
CQQTX::~CQQTX()
|
||
{
|
||
Stop();
|
||
|
||
//删除数据
|
||
if ( m_pDeliverList )
|
||
{delete [] m_pDeliverList;m_pDeliverList=NULL;}
|
||
|
||
DeleteCriticalSection(&m_CriDeliverList);
|
||
|
||
DeleteCriticalSection(&m_CriErrMsg);
|
||
DeleteCriticalSection(&m_CriSendFrame);
|
||
|
||
|
||
|
||
//退出Socket
|
||
WSACleanup();
|
||
}
|
||
|
||
BOOL CQQTX::Connect(const char *pAddr, long lPort, BOOL bReConnect)
|
||
{
|
||
if ( !bReConnect && m_hSocket!=INVALID_SOCKET) //已连接,并且无需重连
|
||
{
|
||
return true;
|
||
}
|
||
|
||
this->Stop(); //重新连接,先让原来的线程停止
|
||
|
||
strcpy( m_szIP,pAddr );
|
||
m_lPort = lPort;
|
||
|
||
sockaddr_in sAddr;
|
||
m_hSocket=socket(AF_INET,SOCK_STREAM,0);
|
||
sAddr.sin_family=AF_INET;
|
||
sAddr.sin_port=0;
|
||
sAddr.sin_addr.s_addr=htonl(INADDR_ANY);
|
||
if (bind(m_hSocket,(LPSOCKADDR)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
|
||
{
|
||
return false;
|
||
}
|
||
sAddr.sin_port=htons((unsigned short)lPort);
|
||
sAddr.sin_addr.s_addr=inet_addr(pAddr);
|
||
if (sAddr.sin_addr.s_addr == INADDR_NONE)
|
||
{
|
||
LPHOSTENT lphost;
|
||
lphost = gethostbyname(pAddr);
|
||
if (lphost != NULL)
|
||
sAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
|
||
else
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
}
|
||
if (connect(m_hSocket,(LPSOCKADDR)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
|
||
//设置Socket
|
||
u_long ulTemp=1; //将SOCKET设成非阻塞式的SOCKET
|
||
//u_long ulTemp=0; //将SOCKET设成阻塞式的SOCKET
|
||
ioctlsocket( m_hSocket,FIONBIO,&ulTemp );
|
||
ulTemp=1024000;
|
||
setsockopt( m_hSocket , SOL_SOCKET, SO_SNDBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
|
||
ulTemp=1024000;
|
||
setsockopt( m_hSocket , SOL_SOCKET, SO_RCVBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
|
||
|
||
m_bQuitThread = false;
|
||
DWORD dwTemp;
|
||
HANDLE m_hThread=CreateThread(NULL,0,SocketRecv,(LPVOID)this,0,&dwTemp);
|
||
// if ( !::AfxBeginThread((AFX_THREADPROC)CNetSocket::SocketRecv,(LPVOID)this,THREAD_PRIORITY_LOWEST) )
|
||
if ( m_hThread == INVALID_HANDLE_VALUE )
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
HANDLE m_hThread_Send=CreateThread(NULL,0,SocketSend,(LPVOID)this,0,&dwTemp);
|
||
// if ( !::AfxBeginThread((AFX_THREADPROC)CNetSocket::SocketRecv,(LPVOID)this,THREAD_PRIORITY_LOWEST) )
|
||
if ( m_hThread_Send == INVALID_HANDLE_VALUE )
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
//SetThreadPriority(m_hThread,THREAD_PRIORITY_LOWEST); //设置优先级
|
||
m_bConnect = true;
|
||
return true;
|
||
}
|
||
|
||
BOOL CQQTX::Connect2()
|
||
{
|
||
sockaddr_in sAddr;
|
||
m_hSocket=socket(AF_INET,SOCK_STREAM,0);
|
||
sAddr.sin_family=AF_INET;
|
||
sAddr.sin_port=0;
|
||
sAddr.sin_addr.s_addr=htonl(INADDR_ANY);
|
||
if (bind(m_hSocket,(LPSOCKADDR)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
|
||
{
|
||
return false;
|
||
}
|
||
sAddr.sin_port=htons((unsigned short)m_lPort);
|
||
sAddr.sin_addr.s_addr=inet_addr(m_szIP);
|
||
if (sAddr.sin_addr.s_addr == INADDR_NONE)
|
||
{
|
||
LPHOSTENT lphost;
|
||
lphost = gethostbyname(m_szIP);
|
||
if (lphost != NULL)
|
||
sAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
|
||
else
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
}
|
||
if (connect(m_hSocket,(LPSOCKADDR)&sAddr,sizeof(sAddr))==SOCKET_ERROR)
|
||
{
|
||
Close();
|
||
return false;
|
||
}
|
||
|
||
//设置Socket
|
||
u_long ulTemp=1; //将SOCKET设成非阻塞式的SOCKET
|
||
//u_long ulTemp=0; //将SOCKET设成阻塞式的SOCKET
|
||
ioctlsocket( m_hSocket,FIONBIO,&ulTemp );
|
||
ulTemp=1024000;
|
||
setsockopt( m_hSocket , SOL_SOCKET, SO_SNDBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
|
||
ulTemp=1024000;
|
||
setsockopt( m_hSocket , SOL_SOCKET, SO_RCVBUF ,(const char *)&ulTemp ,sizeof(ulTemp)); //设绶冲
|
||
return true;
|
||
}
|
||
|
||
BOOL CQQTX::isConnect()
|
||
{
|
||
return m_bConnect;
|
||
}
|
||
|
||
void CQQTX::Stop()
|
||
{
|
||
m_bQuitThread = true;
|
||
if (m_hThread != INVALID_HANDLE_VALUE && WaitForSingleObject(m_hThread,2000) == WAIT_TIMEOUT ) //等待5秒,让线程退出
|
||
{
|
||
TerminateThread(m_hThread,0); //如果退出超时,强制结束线程
|
||
}
|
||
m_hThread = INVALID_HANDLE_VALUE;
|
||
if (m_hThread_Send != INVALID_HANDLE_VALUE && WaitForSingleObject(m_hThread_Send,2000) == WAIT_TIMEOUT ) //等待5秒,让线程退出
|
||
{
|
||
TerminateThread(m_hThread_Send,0); //如果退出超时,强制结束线程
|
||
}
|
||
m_hThread_Send = INVALID_HANDLE_VALUE;
|
||
|
||
Close();
|
||
}
|
||
|
||
BOOL CQQTX::isSocketClose(SOCKET s)
|
||
{
|
||
BOOL bConnDropped = FALSE;
|
||
INT iRet = 0;
|
||
BOOL bOK = TRUE;
|
||
|
||
if (s == INVALID_SOCKET)
|
||
return TRUE;
|
||
|
||
struct timeval timeout = { 0, 0 };
|
||
fd_set readSocketSet;
|
||
FD_ZERO(&readSocketSet);
|
||
FD_SET(s, &readSocketSet);
|
||
iRet = ::select(0, &readSocketSet, NULL, NULL, &timeout);
|
||
bOK = (iRet > 0);
|
||
if(bOK)
|
||
{
|
||
bOK = FD_ISSET(s, &readSocketSet);
|
||
}
|
||
|
||
if(bOK)
|
||
{
|
||
CHAR szBuffer[1] = "";
|
||
iRet = recv(s, szBuffer, 1, MSG_PEEK);
|
||
bOK = (iRet > 0);
|
||
if(!bOK)
|
||
{
|
||
INT iError = WSAGetLastError();
|
||
bConnDropped = (( iError == WSAENETRESET) ||
|
||
(iError == WSAECONNABORTED) ||
|
||
(iError == WSAECONNRESET) ||
|
||
(iError == WSAEINVAL) ||
|
||
(iRet == 0));
|
||
}
|
||
}
|
||
return(bConnDropped);
|
||
}
|
||
|
||
void CQQTX::Close()
|
||
{
|
||
if ( m_hSocket == INVALID_SOCKET )
|
||
return;
|
||
|
||
if ( m_hSocket != INVALID_SOCKET )
|
||
closesocket(m_hSocket);
|
||
|
||
m_hSocket = INVALID_SOCKET;
|
||
m_bConnect = false;
|
||
//m_dwEndSendTime=0;
|
||
//m_dwEndRecvTime=0;
|
||
}
|
||
|
||
long CQQTX::Send(SOCKET sock,BYTE *pData, long lLen)
|
||
{
|
||
#define SOCKET_SEND_TIMEOUT 10000 //10秒发送超时
|
||
if ( sock == INVALID_SOCKET )
|
||
return 0;
|
||
|
||
long lSended = 0;
|
||
DWORD lTimeOut = ::GetTickCount();
|
||
while ( 1 )
|
||
{
|
||
long lRet = send(sock,(char*)(pData+lSended), lLen-lSended,0);
|
||
if ( lRet == SOCKET_ERROR ) //发送错误
|
||
{
|
||
if ( GetLastError() != WSAEWOULDBLOCK ) //绶区已满
|
||
return SOCKET_ERROR;
|
||
}
|
||
|
||
if ( lRet > 0 )
|
||
{
|
||
lSended += lRet;
|
||
if ( lSended >= lLen )
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
Sleep_Lu( 20 ); //绶冲区已满,稍等
|
||
}
|
||
if ( ::GetTickCount() - lTimeOut > SOCKET_SEND_TIMEOUT )
|
||
break;
|
||
}
|
||
return lSended;
|
||
}
|
||
DWORD WINAPI CQQTX::SocketSend(LPVOID lParam)
|
||
{
|
||
CQQTX * pNet = (CQQTX *)lParam;
|
||
QQTX_Data_Recv Drecv={0};
|
||
while ( !pNet->m_bQuitThread )
|
||
{
|
||
//发送短信
|
||
Sleep_Lu(20);
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
DWORD WINAPI CQQTX::SocketRecv(LPVOID lParam)
|
||
{
|
||
CQQTX * pNet = (CQQTX *)lParam;
|
||
QQTX_Data_Recv Drecv={0};
|
||
pNet->m_dwEndRecvTime = ::GetTickCount(); //保存最后接收到帧的时间
|
||
DWORD dwEndSend=GetTickCount();
|
||
while ( !pNet->m_bQuitThread )
|
||
{
|
||
BOOL bReConnect=false;
|
||
if ( isSocketClose(pNet->m_hSocket) )
|
||
{
|
||
pNet->Close();
|
||
//重新接收数据
|
||
if ( Drecv.pRecvFrame )
|
||
delete Drecv.pRecvFrame;
|
||
memset(&Drecv,0,sizeof(Drecv));
|
||
if ( pNet->m_bInitQQTX ) //原已连接的,重新连接
|
||
{
|
||
bReConnect = true;
|
||
}
|
||
else
|
||
{
|
||
pNet->m_bLoginQQTX = -4; //对端断开连接,登录失败
|
||
}
|
||
}
|
||
if ( ReadFrame(pNet->m_hSocket,&Drecv) ) //判断是否有接收到新的Frame
|
||
{
|
||
pNet->m_dwEndRecvTime = ::GetTickCount(); //保存最后接收到帧的时间
|
||
pNet->m_bRecvFrame = true;
|
||
pNet->RecvFrame(Drecv); //处理接收到的帧
|
||
Drecv.lDataLen = 0;
|
||
Drecv.lRecvType = 0;
|
||
if ( Drecv.pRecvFrame )
|
||
{
|
||
delete Drecv.pRecvFrame;
|
||
Drecv.pRecvFrame = NULL;
|
||
}
|
||
}
|
||
//判断接收是否超时
|
||
//if ( pNet->m_dwEndSendTime > 0 && !pNet->m_bRecvFrame)
|
||
if ( pNet->m_dwEndSendTime>0 && ::GetTickCount() - pNet->m_dwEndRecvTime >(QQTX_ACTIVE_TESTTIME*QQTX_ACTIVE_COUNTOUT+QQTX_ACTIVE_TIMEOUT) ) //接收超时
|
||
{
|
||
pNet->m_dwEndRecvTime = ::GetTickCount()-QQTX_ACTIVE_TIMEOUT; //如果接收超时,重新计数
|
||
pNet->Close();
|
||
//重新接收数据
|
||
if ( Drecv.pRecvFrame )
|
||
delete Drecv.pRecvFrame;
|
||
memset(&Drecv,0,sizeof(Drecv));
|
||
bReConnect = true;
|
||
}
|
||
//判断是否应该发送Active_Test指令
|
||
if ( pNet->m_dwEndSendTime > 0 )
|
||
{
|
||
if ( ::GetTickCount() - pNet->m_dwEndSendTime > QQTX_ACTIVE_TESTTIME ) //重新连接
|
||
{
|
||
ULONG lSeq=0;
|
||
pNet->SendFrame(pNet->m_hSocket,pNet->m_lID,pNet->m_dwEndSendTime, QQ_ACTIVE_TEST ,_T(""),lSeq );
|
||
}
|
||
}
|
||
//发送短信
|
||
//pNet->Back_Send();
|
||
|
||
if ( bReConnect )
|
||
{
|
||
for ( int i=0 ; i<30 && !pNet->m_bQuitThread; i++ ) //延时5秒
|
||
{
|
||
Sleep_Lu(100);
|
||
}
|
||
pNet->SetErrMsg("QQTX消息:正在重连网关...");
|
||
if ( !pNet->m_bQuitThread )
|
||
pNet->InitQQTX2(); //重新连接到服务器
|
||
}
|
||
//Sleep_Lu(1);
|
||
}
|
||
if ( Drecv.pRecvFrame )
|
||
delete Drecv.pRecvFrame;
|
||
pNet->Close();
|
||
return 1;
|
||
}
|
||
|
||
void CQQTX::SetRecvProc(QQTX_RECVPROC proc)
|
||
{
|
||
m_pRecvProc = proc;
|
||
}
|
||
|
||
BOOL CQQTX::ReadFrame(SOCKET s, QQTX_Data_Recv *pRecv)
|
||
{
|
||
ULONG nBytes=0;
|
||
ioctlsocket(s,FIONREAD, &nBytes);
|
||
if (nBytes <= 0 )
|
||
{
|
||
Sleep_Lu(20); //没有数据,等待一段时间
|
||
return false;
|
||
}
|
||
|
||
BYTE bTemp=0;
|
||
long lRet=0;
|
||
switch( pRecv->lRecvType )
|
||
{
|
||
case 0://接收头
|
||
lRet = recv(s, (char*)&bTemp,sizeof(bTemp),0);
|
||
if ( lRet > 0 && bTemp==QQ_stx)
|
||
{
|
||
pRecv->lRecvType = 1; //开始接收长度
|
||
pRecv->lDataLen = 0;
|
||
if ( pRecv->pRecvFrame )
|
||
{
|
||
delete pRecv->pRecvFrame;
|
||
pRecv->pRecvFrame = NULL;
|
||
}
|
||
}
|
||
break;
|
||
case 1: //接收长度
|
||
lRet = recv(s, (char*)&pRecv->lDataLen,sizeof(pRecv->lDataLen),0);
|
||
if ( lRet > 0 )
|
||
{
|
||
pRecv->lDataLen = ntohl(pRecv->lDataLen);
|
||
if ( pRecv->lDataLen > 0 && pRecv->lDataLen<4096000)
|
||
{
|
||
pRecv->pRecvFrame = new BYTE[pRecv->lDataLen];
|
||
*((BYTE*)pRecv->pRecvFrame) = QQ_stx; //存好前4个字节
|
||
*((ULONG*)(pRecv->pRecvFrame+1)) = pRecv->lDataLen; //存好前4个字节
|
||
pRecv->lRecvLen = sizeof(pRecv->lDataLen)+1;
|
||
|
||
pRecv->lRecvType = 2; //开始接收数据s
|
||
}
|
||
}
|
||
break;
|
||
case 2: //接收数据
|
||
{
|
||
//计算需要接收的总字节数
|
||
ULONG lBeRecv = pRecv->lDataLen-pRecv->lRecvLen;
|
||
lRet = recv(s,(char*)pRecv->pRecvFrame+pRecv->lRecvLen , lBeRecv ,0);
|
||
if ( lRet > 0 )
|
||
pRecv->lRecvLen += lRet ;
|
||
if ( pRecv->lRecvLen == pRecv->lDataLen ) //Frame 已收满
|
||
{
|
||
pRecv->lDataLen = 0; //重新开始接收
|
||
return true;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
/*
|
||
if ( pRecv->lDataLen <= 0 && nBytes<= sizeof(pRecv->lDataLen) ) //未收够长度信息
|
||
return false;
|
||
|
||
long lRet;
|
||
if (pRecv->lDataLen <= 0 ) //未收到数据,现在开始接收
|
||
{
|
||
lRet = recv(s, (char*)&pRecv->lDataLen,sizeof(pRecv->lDataLen),0);
|
||
if ( lRet > 0 )
|
||
{
|
||
pRecv->lDataLen = ntohl(pRecv->lDataLen);
|
||
if ( pRecv->lDataLen > 0 )
|
||
{
|
||
if ( pRecv->pRecvFrame )
|
||
{
|
||
delete pRecv->pRecvFrame;
|
||
pRecv->pRecvFrame = NULL;
|
||
}
|
||
pRecv->pRecvFrame = new BYTE[pRecv->lDataLen];
|
||
*((long*)pRecv->pRecvFrame) = pRecv->lDataLen; //存好前4个字节
|
||
pRecv->lRecvLen = sizeof(pRecv->lDataLen);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//计算需要接收的总字节数
|
||
ULONG lBeRecv = pRecv->lDataLen-pRecv->lRecvLen;
|
||
lRet = recv(s,(char*)pRecv->pRecvFrame+pRecv->lRecvLen , lBeRecv ,0);
|
||
if ( lRet > 0 )
|
||
pRecv->lRecvLen += lRet ;
|
||
if ( pRecv->lRecvLen == pRecv->lDataLen ) //Frame 已收满
|
||
{
|
||
pRecv->lDataLen = 0; //重新开始接收
|
||
return true;
|
||
}
|
||
}
|
||
*/
|
||
return false;
|
||
}
|
||
|
||
BOOL CQQTX::RecvFrame(QQTX_Data_Recv &Drecv)
|
||
{
|
||
QQTX_Head * pHead=(QQTX_Head *)Drecv.pRecvFrame;
|
||
if ( pHead->Total_Length != Drecv.lRecvLen )
|
||
return false;
|
||
|
||
pHead->Command_Id = ntohl(pHead->Command_Id);
|
||
pHead->Sequence_Id= ntohl(pHead->Sequence_Id);
|
||
|
||
BYTE * pData = (BYTE*)(Drecv.pRecvFrame+sizeof(QQTX_Head));
|
||
long lLen = pHead->Total_Length-sizeof(QQTX_Head)-1;
|
||
CStringA strAnsA((char*)pData,lLen);
|
||
CString strAns = CA2W(strAnsA,CP_UTF8);
|
||
|
||
long lRet = 0;
|
||
switch( pHead->Command_Id )
|
||
{
|
||
case QQ_CONNECT_RESP:
|
||
lRet = Process_Connect(*pHead,strAns);
|
||
break;
|
||
case QQ_ACTIVE_TEST_RESP:
|
||
lRet = Process_Active(*pHead,strAns);
|
||
break;
|
||
default:
|
||
lRet = Process_Other(*pHead,strAns);
|
||
break;
|
||
}
|
||
|
||
return lRet;
|
||
}
|
||
|
||
long CQQTX::QQTX_Init(const TCHAR *pIP,USHORT lPort, const TCHAR *pUser, const TCHAR *pPasswd,const TCHAR * pKey,int lConnectType)
|
||
{
|
||
//记录信息
|
||
strcpy(m_szQQTXIP,CW2A(pIP));
|
||
_tcscpy(m_szQQTXUser,pUser);
|
||
_tcscpy(m_szQQTXPasswd,pPasswd);
|
||
_tcscpy(m_szQQTXKey,pKey);
|
||
m_lConnectType = lConnectType;
|
||
|
||
if ( !Connect(m_szQQTXIP,lPort) )
|
||
{
|
||
return -1; //连接服务器失败
|
||
}
|
||
|
||
CString strReq;
|
||
CString strTemp=_T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")\
|
||
_T("<Req>")\
|
||
_T("<ConnectType>%d</ConnectType>")\
|
||
_T("<UserName>%s</UserName>")\
|
||
_T("<TimeStamp>%s</TimeStamp>")\
|
||
_T("<Password>%s</Password>")\
|
||
_T("</Req>");
|
||
CString strTimeStamp;
|
||
SYSTEMTIME t;GetLocalTime(&t);
|
||
strTimeStamp.Format(_T("%04d%02d%02d%02d%02d%02d"),t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute,t.wSecond);
|
||
CString strUserName = m_szQQTXUser;
|
||
CString strPasswd = m_szQQTXPasswd;
|
||
CString strKey = m_szQQTXKey;
|
||
CString strMd5=CSendPub::GetMD5(strUserName+strKey+strTimeStamp+strPasswd);
|
||
|
||
strReq.Format(strTemp,m_lConnectType,strUserName,strTimeStamp,strMd5);
|
||
|
||
|
||
m_bLoginQQTX = -1;
|
||
ULONG lSeq=0;
|
||
if ( !SendFrame(m_hSocket,m_lID,m_dwEndSendTime,QQ_CONNECT,strReq,lSeq) )
|
||
{
|
||
m_bQuitThread = true;
|
||
return -2; //发送数据失败
|
||
}
|
||
|
||
long lTime = ::GetTickCount();
|
||
while ( m_bLoginQQTX == -1 )
|
||
{
|
||
if ( ::GetTickCount()-lTime > 30000 ) //超时了
|
||
break;
|
||
Sleep_Lu(20);
|
||
}
|
||
if ( m_bLoginQQTX==0 )
|
||
{
|
||
m_bInitQQTX = true; //已初始化
|
||
return m_bLoginQQTX; //返回成功
|
||
}
|
||
if ( m_bLoginQQTX == -1 )
|
||
{
|
||
m_bQuitThread = true;
|
||
return -3; //登录超时
|
||
}
|
||
else
|
||
{
|
||
m_bQuitThread = true;
|
||
return m_bLoginQQTX; //登录返回成功,具体请看错误码
|
||
}
|
||
|
||
m_bQuitThread = true;
|
||
return -4; //其它错误
|
||
}
|
||
|
||
long CQQTX::SendFrame(SOCKET sock,ULONG &lID,DWORD &dwEndSendTime,ULONG lCommandID,CString strReq,ULONG & lSeq )
|
||
{
|
||
EnterCriticalSection(&m_CriSendFrame); //防止冲突
|
||
CStringA strReqA = CW2A(strReq,CP_UTF8);
|
||
long lDataLen = strReqA.GetLength();
|
||
|
||
QQTX_Head head={0};
|
||
long lAllLen;
|
||
head.Total_Length = sizeof(head)+lDataLen+1; //总长度,最后还有个etx
|
||
lAllLen = head.Total_Length;
|
||
head.Command_Id = lCommandID;
|
||
if ( lID >= 0xF000000 ) //重新开始序号
|
||
lID = 1;
|
||
if ( lSeq > 0 )
|
||
head.Sequence_Id = lSeq; //直接使用相同序号的发送
|
||
else
|
||
head.Sequence_Id = lID++;
|
||
lSeq = head.Sequence_Id; //返回
|
||
|
||
head.stx = QQ_stx;
|
||
head.Total_Length = htonl(head.Total_Length);
|
||
head.Command_Id = htonl(head.Command_Id);
|
||
head.Sequence_Id = htonl(head.Sequence_Id);
|
||
|
||
dwEndSendTime = ::GetTickCount(); //记录最后发送时间
|
||
|
||
BYTE * pSData = new BYTE[lAllLen];
|
||
long lSetLen=0;
|
||
memcpy(pSData,&head,sizeof(head));lSetLen+=sizeof(head);
|
||
memcpy(pSData+lSetLen,strReqA.GetBuffer(),lDataLen);lSetLen+=lDataLen;
|
||
pSData[lSetLen]=QQ_etx;lSetLen+=1;
|
||
|
||
BOOL bOK = Send(sock,(BYTE*)pSData , lAllLen );
|
||
delete pSData;
|
||
|
||
long lRet = 0;
|
||
if ( bOK )
|
||
lRet = head.Sequence_Id;
|
||
|
||
LeaveCriticalSection(&m_CriSendFrame); //防止冲突
|
||
return lRet;
|
||
}
|
||
|
||
long CQQTX::Process_Connect(QQTX_Head head,CString strAns)
|
||
{
|
||
CMarkup xml(strAns);
|
||
CString strRetCode;
|
||
CString strErrMsg;
|
||
if ( xml.FindElem(_T("/Ans/RetCode")) )
|
||
strRetCode =xml.GetData();
|
||
if ( xml.FindElem(_T("/Ans/ErrMsg")) )
|
||
strErrMsg =xml.GetData();
|
||
|
||
BOOL bLoginRet = false;
|
||
strRetCode.Trim();
|
||
if ( strRetCode == CString(_T("0")) )
|
||
{
|
||
bLoginRet = true;
|
||
}
|
||
|
||
if ( m_bInitQQTX && !bLoginRet ) //需要重新登录
|
||
{
|
||
//InitQQTX2();
|
||
//登录不成功,关闭连接
|
||
this->Close();
|
||
}
|
||
|
||
CString str;
|
||
str.Format(_T("QQTX消息:连接网关返回代码:%s,%s") , strRetCode,strErrMsg );
|
||
SetErrMsg(str);
|
||
|
||
m_bLoginQQTX = _ttol(strRetCode);
|
||
if (!bLoginRet )
|
||
m_bLoginQQTX = -100;
|
||
return 1;
|
||
}
|
||
|
||
BOOL CQQTX::InitQQTX2()
|
||
{
|
||
m_bLoginQQTX = -1;
|
||
if ( !Connect2() )
|
||
{
|
||
return false; //连接服务器失败
|
||
}
|
||
|
||
|
||
CString strReq;
|
||
CString strTemp=_T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")\
|
||
_T("<Req>")\
|
||
_T("<ConnectType>%d</ConnectType>")\
|
||
_T("<UserName>%s</UserName>")\
|
||
_T("<TimeStamp>%s</TimeStamp>")\
|
||
_T("<Password>%s</Password>")\
|
||
_T("</Req>");
|
||
CString strTimeStamp;
|
||
SYSTEMTIME t;GetLocalTime(&t);
|
||
strTimeStamp.Format(_T("%04d%02d%02d%02d%02d%02d"),t.wYear,t.wMonth,t.wDay,t.wHour,t.wMinute,t.wSecond);
|
||
CString strUserName = m_szQQTXUser;
|
||
CString strPasswd = m_szQQTXPasswd;
|
||
CString strKey = m_szQQTXKey;
|
||
CString strMd5=CSendPub::GetMD5(strUserName+strKey+strTimeStamp+strPasswd);
|
||
|
||
strReq.Format(strTemp,m_lConnectType,strUserName,strTimeStamp,strMd5);
|
||
|
||
|
||
m_bLoginQQTX = -1;
|
||
ULONG lSeq=0;
|
||
if ( !SendFrame(m_hSocket,m_lID,m_dwEndSendTime,QQ_CONNECT,strReq,lSeq) )
|
||
return -2; //发送数据失败
|
||
|
||
//重新连接时,需要重发短信
|
||
|
||
// memset(m_pSendList,0,sizeof(QQTX_Send_List)*SMS_MAX_LIST);
|
||
/*
|
||
for ( int i=0 ; i< SMS_MAX_LIST ;i++ )
|
||
{
|
||
if ( m_pSendList[i].lSendID > 0 )
|
||
{
|
||
m_pSendList[i].lReSendCount = 0;
|
||
m_pSendList[i].lSendTime = 0;
|
||
m_pSendList[i].lSeq = 0;
|
||
}
|
||
}
|
||
*/
|
||
return -4; //其它错误
|
||
}
|
||
|
||
long CQQTX::Process_Active(QQTX_Head head, CString strAns)
|
||
{
|
||
m_dwTestCount = 0; //收到active指令,检测次数为0
|
||
return 1;
|
||
}
|
||
|
||
long CQQTX::Process_Other(QQTX_Head head,CString strAns)
|
||
{
|
||
QQTX_Deliver_List Deliver;
|
||
Deliver.lSendID = head.Sequence_Id;
|
||
Deliver.head = head;
|
||
Deliver.strAns = strAns;
|
||
Deliver_Add(Deliver); //添加到列表
|
||
|
||
|
||
/*
|
||
//发送返回
|
||
QQTX_Deliver_Resp resp={0};
|
||
resp.Msg_ID = pDeliver->Msg_ID;
|
||
resp.Result = 0;
|
||
ULONG lReq=head.Sequence_Id;
|
||
SendFrame(m_hSocket,m_lID,m_dwEndSendTime,QQTX_DELIVER_RESP,(BYTE*)&resp,lReq);
|
||
*/
|
||
|
||
return true;
|
||
}
|
||
|
||
BOOL CQQTX::GetDeliver(QQTX_Deliver_List &deliver)
|
||
{
|
||
EnterCriticalSection(&m_CriDeliverList); //防止冲突
|
||
//从当前点到结尾
|
||
for ( int i=m_lDeliverList ; i< QQTX_MAX_DELIVER; i++ )
|
||
{
|
||
if ( m_pDeliverList[i].lSendID != 0 ) //其等于0时,认为此位置为空
|
||
{
|
||
m_lDeliverList = i+1;
|
||
deliver = m_pDeliverList[i];
|
||
m_pDeliverList[i].lSendID = 0;
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return true;
|
||
}
|
||
}
|
||
//从开头到当前点
|
||
for ( i=0 ; i<m_lDeliverList; i++ )
|
||
{
|
||
if ( m_pDeliverList[i].lSendID != 0 ) //其等于0时,认为此位置为空
|
||
{
|
||
m_lDeliverList = i+1;
|
||
deliver = m_pDeliverList[i];
|
||
m_pDeliverList[i].lSendID = 0;
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return true;
|
||
}
|
||
}
|
||
m_lDeliverList = 0;
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return false;
|
||
}
|
||
|
||
BOOL CQQTX::QQTX_Exit()
|
||
{
|
||
m_bInitQQTX = false; //已初始化
|
||
//ULONG lSeq=0;
|
||
//SendFrame(m_hSocket,m_lID,m_dwEndSendTime,QQTX_TERMINATE,_T(""),lSeq);
|
||
Stop(); //停止
|
||
return true;
|
||
|
||
}
|
||
|
||
BOOL CQQTX::Deliver_Add(QQTX_Deliver_List Deliver)
|
||
{
|
||
EnterCriticalSection(&m_CriDeliverList); //防止冲突
|
||
//从当前点到结尾
|
||
for ( int i=m_lDeliverList ; i< QQTX_MAX_DELIVER; i++ )
|
||
{
|
||
if ( m_pDeliverList[i].lSendID == 0 ) //其等于0时,认为此位置为空
|
||
{
|
||
m_pDeliverList[i] = Deliver;
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return true;
|
||
}
|
||
}
|
||
//从开头到当前点
|
||
for ( i=0 ; i<m_lDeliverList; i++ )
|
||
{
|
||
if ( m_pDeliverList[i].lSendID == 0 ) //其等于0时,认为此位置为空
|
||
{
|
||
m_pDeliverList[i] = Deliver;
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return true;
|
||
}
|
||
}
|
||
LeaveCriticalSection(&m_CriDeliverList); //防止冲突
|
||
return false;
|
||
}
|
||
|
||
void CQQTX::SetSendSpeed(long lSpeed)
|
||
{
|
||
if ( lSpeed<=0 )
|
||
m_lSendInterval = 0;
|
||
else
|
||
m_lSendInterval = 1000/lSpeed;
|
||
}
|
||
|
||
long CQQTX::GetWFSms()
|
||
{
|
||
long lWF=0;
|
||
return lWF;
|
||
}
|
||
|
||
long CQQTX::GetReportSms()
|
||
{
|
||
long lReport=0;
|
||
return lReport;
|
||
}
|
||
|
||
CString CQQTX::GetErrMsg()
|
||
{
|
||
EnterCriticalSection(&m_CriErrMsg); //防止冲突
|
||
|
||
CString strRet;
|
||
if ( m_strErrMsg.GetLength()>0 )
|
||
{
|
||
strRet = m_strErrMsg;
|
||
m_strErrMsg = CString(_T(""));
|
||
}
|
||
LeaveCriticalSection(&m_CriErrMsg); //防止冲突
|
||
return strRet;
|
||
}
|
||
|
||
void CQQTX::SetErrMsg(CString str)
|
||
{
|
||
EnterCriticalSection(&m_CriErrMsg); //防止冲突
|
||
|
||
m_strErrMsg = str;
|
||
|
||
LeaveCriticalSection(&m_CriErrMsg); //防止冲突
|
||
}
|
||
|
||
BOOL CQQTX::isConnectGateWay()
|
||
{
|
||
if ( m_bLoginQQTX == 0 )
|
||
{
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|