www.pudn.com > AVChat1.rar > CTCPListener.cpp


//  
// CTCPListener.cpp 
//  
 
/*-----------------------------------------------------*\ 
			HQ Tech, Make Technology Easy!        
 More information, please go to http://hqtech.nease.net. 
/*-----------------------------------------------------*/ 
 
#include "stdafx.h" 
#include "CTCPListener.h" 
#include "GlobalDefs.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
////////////////////////////////////////////////////////////////////////////// 
CTCPListener::CTCPListener() 
{ 
	mListener  = INVALID_SOCKET; 
	for (int i = 0; i < MAX_COUNT; i++) 
	{ 
		mAccepted[i] = INVALID_SOCKET; 
	} 
 
	mListenPort  = 10028; 
	mLsnThread   = NULL; 
	mIsListening = FALSE; 
} 
 
CTCPListener::~CTCPListener() 
{ 
	DeleteAccepted(); 
	DeleteListener(); 
	StopListening(); 
} 
 
void CTCPListener::SetListenPort(WORD inPort) 
{ 
	mListenPort = inPort; 
} 
 
WORD CTCPListener::GetListenPort(void) 
{ 
	return mListenPort; 
} 
 
// Create a socket and place it in listening state 
BOOL CTCPListener::Create(void) 
{ 
	DeleteListener(); 
 
	int  val  = 0; 
	BOOL pass = FALSE; 
 
	mListener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
	if (mListener != INVALID_SOCKET) 
	{ 
		// Settings on socket 
		BOOL  sopt = TRUE; 
		setsockopt(mListener, IPPROTO_TCP, TCP_NODELAY,  
			(char *)&sopt, sizeof(BOOL)); 
		setsockopt(mListener, SOL_SOCKET, SO_DONTLINGER,  
			(char *)&sopt, sizeof(BOOL)); 
 
		// Bind socket and listen 
		SOCKADDR_IN  addr; 
		memset(&addr, 0, sizeof(SOCKADDR_IN)); 
		addr.sin_family      = AF_INET; 
		addr.sin_addr.s_addr = htonl(INADDR_ANY); 
		addr.sin_port        = htons(mListenPort); 
		val = bind(mListener, (struct sockaddr*) &addr, sizeof(addr)); 
		pass = (val != SOCKET_ERROR); 
	} 
 
	if (pass) 
	{ 
		// Put the socket into the listening status 
		val = listen(mListener, SOMAXCONN); 
		pass = (val != SOCKET_ERROR); 
	} 
 
	if (!pass) 
	{ 
		DeleteListener(); 
	} 
	return pass; 
} 
 
void CTCPListener::DeleteListener(void) 
{ 
	if (mListener != INVALID_SOCKET) 
	{ 
		closesocket(mListener); 
		mListener = INVALID_SOCKET; 
	} 
} 
 
void CTCPListener::DeleteAccepted(void) 
{ 
	for (int i = 0; i < MAX_COUNT; i++) 
	{ 
		if (mAccepted[i] != INVALID_SOCKET) 
		{ 
			closesocket(mAccepted[i]); 
			mAccepted[i] = INVALID_SOCKET; 
		} 
	} 
} 
 
BOOL CTCPListener::StartListening(void) 
{ 
	// Create socket if necessary 
	if (mListener == INVALID_SOCKET) 
	{ 
		Create(); 
	} 
 
	if (mListener != INVALID_SOCKET) 
	{ 
		if (mIsListening) 
		{ 
			return TRUE; 
		} 
 
		DWORD threadID = 0; 
		mLsnThread = CreateThread(NULL, 0, ListeningThrd,  
			this, 0, &threadID); 
		return (mLsnThread != NULL); 
	} 
 
	return FALSE; 
} 
 
void CTCPListener::StopListening(void) 
{ 
	if (mListener != INVALID_SOCKET && mIsListening) 
	{ 
		DeleteListener(); 
		// Make sure the receiving thread has been terminated  
		if (mLsnThread != NULL)  
		{ 
            WaitForSingleObject(mLsnThread, INFINITE); 
			mLsnThread = NULL; 
		} 
	} 
} 
 
BOOL CTCPListener::Accept(void) 
{ 
	if (mListener != INVALID_SOCKET) 
	{ 
		SOCKADDR_IN  saddr; 
		int len = sizeof(SOCKADDR_IN); 
		SOCKET accepted = accept(mListener, (SOCKADDR *)&saddr, &len); 
		if (accepted == INVALID_SOCKET) 
		{ 
			return FALSE; 
		} 
		 
		int index = -1; 
		for (int i = 0; i < MAX_COUNT; i++) 
		{ 
			if (mAccepted[i] == INVALID_SOCKET) 
			{ 
				index = i; 
				break; 
			} 
		} 
 
		if (index != -1) 
		{ 
			mAccepted[index] = accepted; 
			// Settings on socket 
			BOOL sopt = TRUE; 
			setsockopt(accepted, IPPROTO_TCP, TCP_NODELAY,  
				(char *)&sopt, sizeof(BOOL)); 
			setsockopt(accepted, SOL_SOCKET, SO_DONTLINGER,  
				(char *)&sopt, sizeof(BOOL)); 
			// Send a message to the controller 
			Broadcast(msg_TCPSocketAccepted); 
			return TRUE; 
		} 
		else 
		{ 
			closesocket(accepted); 
		} 
	} 
	return FALSE; 
} 
 
// After being fetched out, invalidate the accepted socket 
SOCKET CTCPListener::GetAccepted(int index) 
{ 
	if (index < MAX_COUNT) 
	{ 
		SOCKET ret = mAccepted[index]; 
		mAccepted[index] = INVALID_SOCKET; 
		return ret; 
	} 
	return INVALID_SOCKET; 
} 
 
BOOL CTCPListener::IsSocketReady(void) 
{ 
	for (int i = 0; i < MAX_COUNT; i++) 
	{ 
		if (mAccepted[i] == INVALID_SOCKET) 
		{ 
			return FALSE; 
		} 
	} 
	return TRUE; 
} 
 
DWORD WINAPI CTCPListener::ListeningThrd(void *pParam) 
{ 
	ASSERT(pParam); 
 
	CTCPListener * pListen = (CTCPListener *) pParam; 
	pListen->mIsListening  = TRUE; 
	while (pListen->mIsListening) 
	{ 
		if (!pListen->Accept()) 
		{ 
			pListen->mIsListening = FALSE; 
			break; 
		} 
	} 
 
	return 1; 
}