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

📄 cesocket.cpp

📁 嵌入式WINCE平台下的SOCKET通信程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:

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

	//We cannot connect if the socket is already connected or accepting
	if(m_socketState > CREATED)
	{
		m_errorCode = WSAEISCONN;
		return FALSE;
	}

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

	memset(&m_localAddress, 0, sizeof(SOCKADDR_IN));
	m_localAddress.sin_family = AF_INET;
	m_localAddress.sin_port = htons(localPort);
	m_localAddress.sin_addr.s_addr = htonl(INADDR_ANY);

	if(bind(s, (SOCKADDR*) &m_localAddress, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
	{
		m_errorCode = WSAGetLastError();
		return FALSE;
	}
	
	//UDP needs only bind
	if(m_socketType == SOCK_DGRAM)
	{
		m_socketState = ACCEPTING;
		m_udpReadyToSend = FALSE;
		//Start reading thread
		m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
		return TRUE;
	}

	//The following is TCP listen + accept code

	if(listen(s, maxConn) == SOCKET_ERROR)
	{
		m_errorCode = WSAGetLastError();
		return FALSE;
	}

	m_socketState = ACCEPTING;
	m_acceptThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );

	return TRUE;
}

void CCESocket::AcceptServiceSocket(SOCKET serviceSocket)
{
	SOCKADDR_IN peerName;
	int nameSize = sizeof(SOCKADDR_IN);

	//Is it a valid socket?
	if(serviceSocket == INVALID_SOCKET)
		return;

	//Is it connected?
	if(getpeername(serviceSocket, (SOCKADDR*) &peerName, &nameSize) == SOCKET_ERROR)
	{
		shutdown(serviceSocket, SD_BOTH);
		closesocket(serviceSocket);
		return;
	}

	Disconnect();
	s = serviceSocket;

	if(m_recvBufSize == 0)
		m_recvBufSize = TCPBUFFERSIZE;

	m_socketState = CONNECTED;
	m_readThread = CreateThread(NULL, 0, StartThread, this, 0, NULL );
}

DWORD WINAPI CCESocket::StartThread(LPVOID pParam)
{
	CCESocket *parent = (CCESocket*) pParam;

	if(parent->m_socketState == ACCEPTING && parent->m_socketType == SOCK_STREAM)
		parent->AcceptThread();
	else
		parent->ReadThread();
	
	return 0;
}

void CCESocket::AcceptThread()
{
	SOCKET serviceSocket;

	m_acceptThreadState = RUNNING;

	do 
	{
		memset(&m_remoteAddress, 0, sizeof(SOCKADDR_IN));
		serviceSocket = accept(s, (SOCKADDR*) &m_remoteAddress, &m_receiveAddrSz);			
		if(serviceSocket == SOCKET_ERROR)
		{
			m_errorCode = WSAGetLastError();
			break;
		}

		//Accepts a new connection
		if(!OnAccept(serviceSocket))
		{
			shutdown(serviceSocket, SD_BOTH);
			closesocket(serviceSocket);
		}

	} while(m_acceptThreadState == RUNNING);

	m_acceptThreadState = CLOSING;
	if(m_socketState > DISCONNECTING)
	{
		Disconnect();
		OnClose(EVN_SERVERDOWN);
	}	
	// Self terminate the thread
	m_acceptThreadState = CLOSED;
	m_acceptThread = NULL;
	ExitThread(WM_QUIT);
}

// Read any incoming data as well as detect the connected lost/reset
void CCESocket::ReadThread()
{
	int bytesRead, bufSize;
	DataPacket *data;
	char * buf;

	m_readThreadState = RUNNING;

	do 
	{
		//m_recvBuffSize can change dynamically so we must track its changes
		bufSize = m_recvBufSize;
		buf = new char[bufSize];
		//Blocking receive
		switch(m_socketType)
		{
			case SOCK_STREAM:
				bytesRead = recv(s, buf, bufSize, 0);
				break;
			case SOCK_DGRAM:
				bytesRead = recvfrom(s, buf, bufSize, 0, (SOCKADDR*) &m_localAddress, &m_receiveAddrSz);
				break;
		}
		//If there was an error exit thread and notify owner with OnClose
		if(bytesRead == SOCKET_ERROR || bytesRead <= 0)
		{
			m_errorCode = WSAGetLastError();
			m_udpReadyToSend = FALSE;
			//This happens when we try to sendto data to a client host that closed its receiving
			//port. In this case we restart revfrom preventing further sendto until a new
			//request from a client host.
			if(m_socketType == SOCK_DGRAM && m_errorCode == WSAECONNRESET && m_socketState == ACCEPTING)
			{
				delete[] buf;
				//Notify that a remote connection closed
				OnClose(EVN_CONNLOST);
				continue;
			}
			break;
		}
		
		m_udpReadyToSend = TRUE;

		//If the client doesn't accepts the raw packet store it in the buffer
		if(!OnReceive(buf, bytesRead))
		{
			data = new DataPacket;
			data->len = bytesRead;
			data->buf = buf;
			data->pos = buf;
			
			//AddTail modifies internal list pointers. That's why we
			//need to lock while updating
#ifdef _WCE_SECTION
			EnterCriticalSection(&CCESocket::m_readLock);
#else
			CSingleLock csl(&CCESocket::m_readLock);
			csl.Lock();
#endif
			
			m_ReadBuffer.AddTail(data);
			
#ifdef _WCE_SECTION
			LeaveCriticalSection(&CCESocket::m_readLock);
#else
			csl.Unlock();
#endif
			
			m_availableData += bytesRead;
			
			//Notify that there are available data
			OnReceive();
		}

	} while(m_readThreadState == RUNNING);

	delete[] buf;
	m_readThreadState = CLOSING;
	if(m_socketState > DISCONNECTING)
	{
		if(m_socketType == SOCK_STREAM)
		{
			Disconnect();
			OnClose(EVN_CONNCLOSED);
		}
		else
		{
			m_socketState = CREATED;
			if(m_socketState == ACCEPTING)
				OnClose(EVN_SERVERDOWN);
			else
				OnClose(EVN_CONNLOST);
		}
	}	
	// Self terminate the thread
	m_readThreadState = CLOSED;
	m_readThread = NULL;
	// ExitThread(WM_QUIT);
}

int CCESocket::Read(char* buf, int len)
{
	int readBytes;
	DataPacket *data;

	if(!buf || len <= 0)
		return 0;
	
	readBytes = 0;

	while (m_ReadBuffer.GetNumEntries() > 0 && len > 0)
	{
		data = m_ReadBuffer.GetHead();

		//copies head packet and removes it from the buffer
		if(len >= data->len)
		{
			memcpy(&buf[readBytes], data->pos, data->len);
			len -= data->len;
			readBytes += data->len;
			delete[] data->buf;

			//RemoveHead modifies internal list pointers. That's why we
			//need to lock while updating
#ifdef _WCE_SECTION
			EnterCriticalSection(&CCESocket::m_readLock);
#else
			CSingleLock csl(&CCESocket::m_readLock);
			csl.Lock();
#endif
			
			delete m_ReadBuffer.RemoveHead();
			
#ifdef _WCE_SECTION
			LeaveCriticalSection(&CCESocket::m_readLock);
#else
			csl.Unlock();
#endif
		}
		//copies len data from the head packet and (fast) resizes it
		else
		{
			memcpy(&buf[readBytes], data->pos, len);
			data->len -= len;
			data->pos += len;
			readBytes += len;
			break;
		}
	}
	m_availableData -= readBytes;
	
	return readBytes;
}

bool CCESocket::ReadString(CString &str)
{
	bool strFound;
	int strSize, strPos;
	DataPacket *data;
	char *buf;
	char eol;

	strSize = 0;
	strFound = FALSE;

	if(m_eolFormat == EOL_NULL)
		eol = '\0';
	else
		eol = '\n';

	//We must do a double pass:
	// 1) Search for the string termination '\n'
	// 2) Copy string data
	if(!m_ReadBuffer.IsEmpty())
	{
		//First pass
		data = m_ReadBuffer.GetHead();
		for(strPos=0; strPos < data->len; strPos++)
			if(data->pos[strPos] == eol)
			{
				strSize = strPos +1;
				strFound = TRUE;
				break;
			}
		while(!strFound && !m_ReadBuffer.IsLast())
		{
			strSize += data->len;
			data = m_ReadBuffer.GetNext();
			for(strPos=0; strPos < data->len; strPos++)
				if(data->pos[strPos] == eol)
				{
					strSize += strPos +1;
					strFound = TRUE;
					break;
				}
		}
		//Second pass
		if(strFound)
		{
			strPos = 0;
			m_availableData -= strSize;
			buf = new char[strSize +1];
			buf[strSize] = '\0';
			while (strSize > 0)
			{
				data = m_ReadBuffer.GetHead();

				//copies head packet and removes it from the buffer
				if(strSize >= data->len)
				{
					memcpy(&buf[strPos], data->pos, data->len);
					strSize -= data->len;
					strPos += data->len;
					delete[] data->buf;

					//RemoveHead modifies internal list pointers. That's why we
					//need to lock while updating
					#ifdef _WCE_SECTION
						EnterCriticalSection(&CCESocket::m_readLock);
					#else
						CSingleLock csl(&CCESocket::m_readLock);
						csl.Lock();
					#endif

					delete m_ReadBuffer.RemoveHead();

					#ifdef _WCE_SECTION
						LeaveCriticalSection(&CCESocket::m_readLock);
					#else
						csl.Unlock();
					#endif
				}
				//copies len data from the head packet and (fast) resizes it
				else
				{
					memcpy(&buf[strPos], data->pos, strSize);
					data->len -= strSize;
					data->pos += strSize;
					break;
				}
			}
			str = buf; //Assign and convert to unicode
			delete[] buf;
			return TRUE;
		}		
	}
	str = _T("");
	return FALSE;
}

int CCESocket::GetNumPackets()
{
	return m_ReadBuffer.GetNumEntries();
}

int CCESocket::GetPacketSize()
{
	if(m_availableData > 0)
		return m_ReadBuffer.GetHead()->len;

	return 0;
}

bool CCESocket::GetPacket(char*& buf, int* len)
{
	DataPacket *data = NULL;

	//There's no need to lock while accessing data
	if(m_availableData > 0)
	{
		data = m_ReadBuffer.GetHead();
		*len = data->len;
		buf = data->buf;
		m_availableData -= *len;

		//RemoveHead modifies internal list pointers. That's why we
		//need to lock while updating
		#ifdef _WCE_SECTION
			EnterCriticalSection(&CCESocket::m_readLock);
		#else
			CSingleLock csl(&CCESocket::m_readLock);
			csl.Lock();
		#endif
		
			delete m_ReadBuffer.RemoveHead();

		#ifdef _WCE_SECTION
			LeaveCriticalSection(&CCESocket::m_readLock);
		#else
			csl.Unlock();
		#endif
	}
	
	return (data != NULL);
}

⌨️ 快捷键说明

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