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

📄 cesocket.cpp

📁 嵌入式WINCE平台下的SOCKET通信程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This Winsock Wrapper replaces all MFC socket classes (CSocket, CAsyncSocket
// CCeSocket). It offers async notifications, buffered read and easy data access
// functions.
//
// Coded by Marco Zaratti / marco.zaratti@gmail.it / 2006.04.05
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "CESocket.h"
#include <stdlib.h>
#include <afxmt.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

bool CCESocket::m_bWSAStarted = FALSE;
#ifdef _WCE_SECTION
	CRITICAL_SECTION CCESocket::m_readLock;
#else
	CCriticalSection CCESocket::m_readLock;
#endif

CCESocket::CCESocket()
{
	WSADATA wsaData;

	s = INVALID_SOCKET;
	m_socketType = SOCK_STREAM;
	m_socketState = NONE;
	m_readThread = NULL;
	m_acceptThread = NULL;
	m_readThreadState = CLOSED;
	m_acceptThreadState = CLOSED;
	m_udpReadyToSend = FALSE;
	m_receiveAddrSz = sizeof(SOCKADDR_IN);
	m_eolFormat = EOL_LFCR;
	m_errorCode = 0;
	m_recvBufSize = 0;
#ifdef _WCE_SECTION
	InitializeCriticalSection(&CCESocket::m_readLock);
#endif
	m_availableData = 0;

	if(!m_bWSAStarted)
	{
		m_errorCode = WSAStartup(MAKEWORD(2,2), &wsaData);
		if(m_errorCode == 0)
			m_bWSAStarted = TRUE;
	}
}

CCESocket::~CCESocket()
{
	int watchDog;

//	HANDLE readThread, acceptThread;
// 	readThread = m_readThread;
// 	acceptThread = m_acceptThread;

	Disconnect();

	watchDog = 0;
	while (m_readThread)
	{
		SetThreadPriority(m_readThread, THREAD_PRIORITY_HIGHEST);
		if((::WaitForSingleObject(m_readThread, 1000) != WAIT_TIMEOUT) ||
			watchDog >= THREAD_TERMINATION_MAXWAIT)
		{
			CloseHandle(m_readThread);
			m_readThread = NULL;
		}
		watchDog++;
	}
	watchDog = 0;
	while (m_acceptThread)
	{
		SetThreadPriority(m_acceptThread, THREAD_PRIORITY_HIGHEST);
		if((::WaitForSingleObject(m_acceptThread, 1000) != WAIT_TIMEOUT) ||
			watchDog >= THREAD_TERMINATION_MAXWAIT)
		{
			CloseHandle(m_acceptThread);
			m_acceptThread = NULL;
		}
		watchDog++;
	}

	m_ReadBuffer.ClearData();

#ifdef _WCE_SECTION
	DeleteCriticalSection(&CCESocket::m_readLock);
#endif
}

void CCESocket::SetBufferSize(int bufSize)
{
	if(bufSize > 0)
		m_recvBufSize = bufSize;
}

bool CCESocket::Create(int socketType, int bufferSize)
{
	BOOL dontLinger = TRUE;
	LINGER lingerOpt;

	if(!m_bWSAStarted)
		return FALSE;

	//Exit if the socket has been already created
	if(s != INVALID_SOCKET)
	{
		m_errorCode = WSAEACCES;
		return FALSE;
	}

	switch(socketType)
	{
		case SOCK_STREAM:
			s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
			break;
		case SOCK_DGRAM:
			s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
			break;
		default:
			m_errorCode = WSAEINVAL;
			return FALSE;
	}
	
	if(s == INVALID_SOCKET)
	{
		m_errorCode = WSAGetLastError();
		return FALSE;
	}

	switch(socketType)
	{
		case SOCK_STREAM:
			lingerOpt.l_onoff = 0;
			lingerOpt.l_linger = 0;

			if(setsockopt(s, SOL_SOCKET, SO_DONTLINGER, (char*) &dontLinger, sizeof(BOOL)) != 0)
			{
				m_errorCode = WSAGetLastError();
				closesocket(s);
				return FALSE;
			}

			if(setsockopt(s, SOL_SOCKET, SO_LINGER, (char*) &lingerOpt, sizeof(LINGER)) != 0)
			{
				m_errorCode = WSAGetLastError();
				closesocket(s);
				return FALSE;
			}

			if(bufferSize == 0)
				bufferSize = TCPBUFFERSIZE;
			break;
		case SOCK_DGRAM:
			if(bufferSize == 0)
				bufferSize = UDPBUFFERSIZE;
			m_udpReadyToSend = FALSE;
			break;
	}
	m_recvBufSize = bufferSize;
	m_ReadBuffer.ClearData();
	m_availableData = 0;

	//OK, all done
	m_socketType = socketType;
	m_socketState = CREATED;
	return TRUE;
}

bool CCESocket::Connect(CString &addr, UINT remotePort)
{
	char hostStr[257];
	int wHostLen;
	LPTSTR wHost;
	ulong hostByIP;
	HOSTENT *hostByName;

	if(!m_bWSAStarted)
		return FALSE;

	//Make sure the socket was created
	if(s == INVALID_SOCKET)
	{
		m_errorCode = WSAENOTSOCK;
		return FALSE;
	}

	//We cannot connect if the socket is already connected (TCP only)
	if(m_socketType == SOCK_STREAM && m_socketState > CREATED)
	{
		m_errorCode = WSAEISCONN;
		return FALSE;
	}

	//We cannot connect if the socket is listening (UDP only)
	if(m_socketType == SOCK_DGRAM && m_socketState > CONNECTED)
	{
		m_errorCode = WSAEISCONN;
		return FALSE;
	}

	//Check port values
	if(remotePort > 65535)
	{
		m_errorCode = WSAEINVAL;
		return FALSE;
	}

	//Gets address string and convert it from unicode to multibyte
	wHostLen = addr.GetLength();
	if(wHostLen > 256)
		wHostLen = 256;
	wHost = addr.GetBuffer(wHostLen);
#ifdef _WIN32_WCE
	wcstombs(hostStr, wHost, 256);
#else
	wHost[wHostLen] = '\0';
	strcpy(hostStr, wHost);
	addr.ReleaseBuffer();
#endif
	
	//Builds destination address
	memset(&m_remoteAddress, 0, sizeof(SOCKADDR_IN));
	m_remoteAddress.sin_family = AF_INET;
	m_remoteAddress.sin_port = htons(remotePort);

	hostByIP = inet_addr(hostStr);
	if(hostByIP == INADDR_NONE)
	{
		hostByName = gethostbyname(hostStr);
		if(hostByName == NULL)
		{
			m_errorCode = WSAGetLastError();
			return FALSE;
		}
		m_remoteAddress.sin_addr = *((IN_ADDR*)hostByName->h_addr_list[0]);
	}
	else
		m_remoteAddress.sin_addr.s_addr = hostByIP;
	
	//Connects if TCP.
	//UDP is connectionless. However we'll use m_remoteAddress for sending data.
	if(m_socketType == SOCK_STREAM)
	{
		if(connect(s, (SOCKADDR*) &m_remoteAddress, sizeof(SOCKADDR_IN)) != 0)
		{
			m_errorCode = WSAGetLastError();
			return FALSE;
		}
		m_socketState = CONNECTED;

		//TCP: Start reading thread
		//UDP: Can't start it now, we must first do a sendto to bind to a local port
		m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
	}
	else
	{
		m_udpReadyToSend  = TRUE;
		m_socketState = CONNECTED;
	}

	return TRUE;
}

void CCESocket::Disconnect()
{
	if(!m_bWSAStarted || s == INVALID_SOCKET)
		return;

	//After a shutodown reading thread will self terminate
	m_socketState = DISCONNECTING;
	shutdown(s, SD_BOTH);
	closesocket(s);
	s = INVALID_SOCKET;
	m_socketState = NONE;
	m_errorCode = 0;
	m_udpReadyToSend = FALSE;
}

int CCESocket::Send(CString& str)
{
	int sentBytes, len;
	char* buf;
	LPTSTR strBuf;

	len = str.GetLength();
	strBuf = str.GetBuffer(len);
#ifdef _WIN32_WCE
	buf = new char[len];
	wcstombs(buf, strBuf, len);
#else
	buf = (char*) strBuf;
#endif

	sentBytes = Send(buf, len);

#ifdef _WIN32_WCE
	delete[] buf;
#endif

	return sentBytes;
}

int CCESocket::SendLine(CString& str)
{
	int sentBytes, len;
	char* buf;
	LPTSTR strBuf;

	len = str.GetLength();
	strBuf = str.GetBuffer(len);
	buf = new char[len+2];
#ifdef _WIN32_WCE
	wcstombs(buf, strBuf, len);
#else
	memcpy(buf, strBuf, len);
#endif

	switch(m_eolFormat)
	{
		case EOL_LFCR:
			buf[len] = '\r';
			buf[len+1] = '\n';
			sentBytes = Send(buf, len+2);
			break;
		case EOL_CR:
			buf[len] = '\n';
			sentBytes = Send(buf, len+1);
			break;
		case EOL_NULL:
			buf[len] = '\0';
			sentBytes = Send(buf, len+1);
			break;
	}

	delete[] buf;
	return sentBytes;
}

int CCESocket::Send(const char* buf, int len)
{
	int dataPtr = 0;
	int sentBytes = 0;

	if(!m_bWSAStarted)
		return SOCKET_ERROR;

	//We cannot send data if the socket's not connected
	if(m_socketState < CONNECTED)
	{
		m_errorCode = WSAENOTCONN;
		return SOCKET_ERROR;
	}

	//TCP listening socket cannot send data
	if(m_socketState == ACCEPTING && m_socketType == SOCK_STREAM)
	{
		m_errorCode = WSAENOTCONN;
		return SOCKET_ERROR;
	}

	//Have we a valid buffer?
	if(!buf || len <= 0)
	{
		m_errorCode = WSAEFAULT;
		return SOCKET_ERROR;
	}

	switch(m_socketType)
	{
	case SOCK_STREAM:
		while(len > 0)
		{
			sentBytes = send(s, &buf[dataPtr], len, 0);
			if(sentBytes == SOCKET_ERROR)
			{
				m_errorCode = WSAGetLastError();
				return SOCKET_ERROR;
			}
			dataPtr += sentBytes;
			len -= sentBytes;
		}
		break;
	case SOCK_DGRAM:
		if(m_udpReadyToSend)
		{
			while(len > 0)
			{
				if(m_socketState == ACCEPTING)
					sentBytes = sendto(s, &buf[dataPtr], len, 0, (SOCKADDR*) &m_localAddress, sizeof(m_localAddress));
				else
					sentBytes = sendto(s, &buf[dataPtr], len, 0, (SOCKADDR*) &m_remoteAddress, sizeof(m_remoteAddress));
				if(sentBytes == SOCKET_ERROR)
				{
					m_errorCode = WSAGetLastError();
					return SOCKET_ERROR;
				}
				dataPtr += sentBytes;
				len -= sentBytes;
			}

			//In client mode: after the first sendto we can start the reading thread
			//because we now have an implicit bind on a local port
			//In server mode: the thread is already running so this if is never true.
			if(m_readThreadState == CLOSED)
			{
				m_readThreadState = RUNNING;
				m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
			}
		}
	}

	return dataPtr;
}

bool CCESocket::Accept(UINT localPort, int maxConn)
{
	if(!m_bWSAStarted)
		return FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -