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

📄 serverlink.cpp

📁 一个短信smpp协议开发包源码
💻 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 + -