📄 serverlink.cpp
字号:
// ServerLink.cpp: implementation of the CServerLink class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
//#include "SMPPAPI.h"
#include "ServerLink.h"
#include "common.h"
#include "smpp.h"
#include "smpppacket.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CServerLink::CServerLink() : m_bConnected(false), m_nSocket(INVALID_SOCKET),
m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
{
m_nSocket = NULL;
m_hEvent = NULL;
m_hThread = NULL;
m_pIOWinThread = NULL;
//manual reset Kill event with intial signal state to false
m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//callback
m_Param = NULL;
m_pProcessPacket = NULL;
InitializeCriticalSection(&m_cs);
}
CServerLink::CServerLink(CString svrip) : m_bConnected(false), m_nSocket(INVALID_SOCKET),
m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
{
m_ServerIP = svrip;
m_ServerPort = DEFAULT_PORT;
m_nSocket = NULL;
m_hEvent = NULL;
m_hThread = NULL;
m_pIOWinThread = NULL;
//manual reset Kill event with intial signal state to false
m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//callback
m_Param = NULL;
m_pProcessPacket = NULL;
InitializeCriticalSection(&m_cs);
}
CServerLink::CServerLink(CString svrip, int port) : m_bConnected(false), m_nSocket(INVALID_SOCKET),
m_hEvent(WSA_INVALID_EVENT), m_bReadHeader(true)
{
m_ServerIP = svrip;
m_ServerPort = port;
m_nSocket = NULL;
m_hEvent = NULL;
m_hThread = NULL;
m_pIOWinThread = NULL;
//manual reset Kill event with intial signal state to false
m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hDisconnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//callback
m_Param = NULL;
m_pProcessPacket = NULL;
InitializeCriticalSection(&m_cs);
}
CServerLink::~CServerLink()
{
SetEvent(m_hKillEvent);
WaitForSingleObject(m_hThread, 500);
CloseHandle(m_hKillEvent);
WSACloseEvent(m_hEvent);
CloseHandle(m_hDisconnectEvent);
DeleteCriticalSection(&m_cs);
}
void CServerLink::init(CString svrip, int port)
{
m_ServerIP = svrip;
m_ServerPort = port;
}
bool CServerLink::open()
{
EnterCriticalSection(&m_cs);
bool bConnected = m_bConnected;
LeaveCriticalSection(&m_cs);
if (bConnected)
return true;
SOCKADDR_IN saServer;
saServer.sin_port = htons(m_ServerPort);
saServer.sin_family = AF_INET;
saServer.sin_addr.s_addr = inet_addr(m_ServerIP);
m_nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_nSocket == INVALID_SOCKET)
{
return FALSE;
}
int nRet = connect(m_nSocket,(sockaddr*)&saServer, sizeof(saServer));
if (nRet == SOCKET_ERROR)
{
TCHAR buf[100];
sprintf(buf, "connect error %ld",WSAGetLastError());
closesocket(m_nSocket);
return FALSE;
}
ResetEvent(m_hDisconnectEvent);
m_bConnected = TRUE;
TRACE("Connected to Server");
//listen to event
m_hEvent = WSACreateEvent();
//first, we tell the system what event we are interested
nRet = WSAEventSelect(m_nSocket,
m_hEvent,
FD_CLOSE | FD_READ);
//create the thread to listen for events
m_pIOWinThread = AfxBeginThread(IOThreadProc, //thread proc
(void*) this, //parameter
THREAD_PRIORITY_NORMAL, //thread priority
0, //stack size
CREATE_SUSPENDED, //create thread
NULL); //security attribute
m_dwThreadId = m_pIOWinThread->m_nThreadID;
m_hThread = m_pIOWinThread->m_hThread;
m_pIOWinThread->ResumeThread();
TRACE("Listen TID=%ld\n",m_dwThreadId);
return TRUE;
}
void CServerLink::close()
{
EnterCriticalSection(&m_cs);
if (m_bConnected)
{
SetEvent(m_hKillEvent);
WaitForSingleObject(m_hThread, 2000);
closesocket(m_nSocket);
SetEvent(m_hDisconnectEvent);
m_bConnected = FALSE;
}
LeaveCriticalSection(&m_cs);
}
bool CServerLink::isConnected()
{
return m_bConnected;
}
CString CServerLink::getServerIP()
{
return m_ServerIP;
}
int CServerLink::getServerPort()
{
return m_ServerPort;
}
UINT CServerLink::IOThreadProc(LPVOID pParam)
{
return ((CServerLink *) pParam)->IOThreadRun();
}
unsigned CServerLink::IOThreadRun()
{
bool bRunning = false;
bool bConnected;
TRACE("Going to run the IO Thread\n");
while (!bRunning)
{
EnterCriticalSection(&m_cs);
bConnected = m_bConnected;
LeaveCriticalSection(&m_cs);
//if it's not connected exit the IO thread
if(!m_bConnected)
break;
//going to shutdown, exit the loop
if (WaitForSingleObject(m_hKillEvent, 0) == WAIT_OBJECT_0)
{
TRACE("Existing IO Thread coz of kill event\n");
break;
}
DWORD ret = ::WSAWaitForMultipleEvents(1, &m_hEvent, FALSE, 100, FALSE);
if (ret == WSA_WAIT_EVENT_0 ) //an event is signalled
{
WSANETWORKEVENTS hNetworkEvent;
//evaluate what's happend, read or close ?
int ret1 = ::WSAEnumNetworkEvents(m_nSocket, m_hEvent, &hNetworkEvent);
if (hNetworkEvent.lNetworkEvents & FD_CLOSE)
{
TRACE("Network event is Close\n");
OnClose();
break;
}
if (hNetworkEvent.lNetworkEvents & FD_READ) //we got something to read
{
TRACE("Network event is Read\n");
OnRead();
}
} //wait_object_0
} //while bRunning
TRACE("Exiting IO Thread\n");
return 0; //thread exit normally
}
bool CServerLink::OnRead()
{
TRACE("OnRead - CServerLink\n");
int ret;
if (m_bReadHeader)
{
m_nTotalRead = 0;
DWORD dwRead = 0;
//check how many bytes we could read
ioctlsocket(m_nSocket, FIONREAD, &dwRead);
//can we get the preliminary header ?
//we know the packet size after reading it
if (dwRead < 4)
return false;
BYTE pkt_hdr[4];
ret = recv(m_nSocket, (char *) pkt_hdr, 4,0);
m_nTotalRead = 4; //CommandLen is included in the length
m_nBlockSize = readInt(pkt_hdr);
TCHAR buff[100];
sprintf(buff, "CommandLen is : %d\n", m_nBlockSize);
TRACE(buff);
m_bReadHeader = FALSE; //we don't have to read header later
}
else
{
//we have already read the 4-byte preliminary header
DWORD dwRead = 0;
//check that how many bytes we can read
ioctlsocket(m_nSocket, FIONREAD, &dwRead);
if (dwRead == 0)
return false;
//we should only read the socket up to packet size as in the header
if (dwRead > (m_nBlockSize - m_nTotalRead))
dwRead = m_nBlockSize - m_nTotalRead;
BYTE* pBlock = new BYTE[dwRead+1];
ZeroMemory(pBlock, dwRead+1);
int nrec = recv(m_nSocket, (char*) pBlock, dwRead, 0);
pBlock[dwRead] = NULL;
m_nTotalRead+=nrec;
if (m_nTotalRead == m_nBlockSize)
{
//we get the whole packet in pBlock
parse_packet(pBlock, m_nTotalRead);
//resetting
m_bReadHeader = TRUE;
}
delete [] pBlock;
}
return false;
}
bool CServerLink::OnClose()
{
close();
CLinkClose *ppak = new CLinkClose();
//call back
if (m_pProcessPacket != NULL)
{
m_pProcessPacket(ppak, m_Param);
}
delete ppak;
return true;
}
int CServerLink::send(PBYTE data, uint32 datalen)
{
WSABUF sbuffer;
ULONG cb_written, retcode = 0;
int ret;
if (!m_bConnected)
return 0;
sbuffer.len = datalen;
sbuffer.buf = (char *) data;
retry:
//send
ret = WSASend (m_nSocket, (LPWSABUF)&sbuffer, 1, &cb_written, 0, NULL, NULL);
if (ret != 0) {
ret = WSAGetLastError();
if (ret == WSAEWOULDBLOCK) {
Sleep(100);
goto retry;
}
return ret;
}
if (datalen != cb_written) {
// not all data send!
return -1;
}
return 0;
}
bool CServerLink::sendPacket(CPacketBase &pak)
{
bool ret;
PBYTE pby;
int nsz;
pak.encodeBody(pby, nsz);
if( send(pby, nsz) > 0)
ret = true;
else
ret = false;
delete [] pby;
return ret;
}
void CServerLink::registerProcessPacket(void(__stdcall *start_address)(CPacketBase *pak, LPVOID param), LPVOID param)
{
m_pProcessPacket = start_address;
m_Param = param;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -