www.pudn.com > udpsocket.rar > UdpSocket.cpp


/***************************************************************** 
 
	Description: 
 
		The definition for the class "CUdpSocket". 
 
	Author:		tief@mail.eastcomtd.com 
 
	Created date:	2002/10/30 14:00 PM 
 
 
*****************************************************************/ 
 
#include "UdpSocket.h" 
 
#include  
 
#ifdef WIN32 
 
	#include  
 
#endif 
 
#ifdef VXWORKS 0 
 
	#include  
	#include  
	#include  
 
#endif 
 
#include  
 
#ifdef _DEBUG 
 
	#include  
 
#endif 
 
#ifdef VXWORKS 0 
 
	#define INVALID_SOCKET ERROR 
	#define SOCKET_ERROR ERROR 
 
#endif 
 
CUdpSocket::CUdpSocket() 
{ 
 
#ifdef WIN32 
 
	WSADATA wsd ; 
 
	// Load the windows socket DLLs and initialize 
	// the members. 
 
	WSAStartup(MAKEWORD(2,2),&wsd) ; 
 
	m_hThread = NULL ; 
 
#endif 
 
#ifdef VXWORKS 0 
 
	m_hTask = NULL ; 
 
#endif 
 
	m_wm = user_receive ; 
	m_bReady = false ; 
	m_sockSender = NULL ; 
	m_sockReceiver = NULL ; 
 
	m_tvDelay.tv_sec=0 ; 
	m_tvDelay.tv_usec=1 ; 
 
	memset(&m_addrRemote,0,sizeof(SOCKADDR)) ; 
} 
 
STATUS CUdpSocket::SetWorkMode(workmode wm) 
{ 
	if (m_bReady) return CANNOT_SETMODE ; 
 
	m_wm = wm ; 
	return OK ; 
} 
 
STATUS CUdpSocket::Init 
	(int localport,const char * targetip,int remoteport) 
{ 
	// Create the socket for data sending 
 
	if ((m_sockSender=socket(AF_INET,SOCK_DGRAM,0)) 
		==INVALID_SOCKET) 
	{ 
 
#ifdef _DEBUG 
 
 		printf("run time error:") ; 
 		printf("cann't create sender (socket).\n") ; 
 
#endif 
 
		OnInitComplete(SOCKET_CALL_FAILD) ; 
 
		return SOCKET_CALL_FAILD ; 
	} 
 
	// Set port and remote host for sender 
 
	m_addrRemote.sin_family=AF_INET ; 
	m_addrRemote.sin_port=htons((short)remoteport) ; 
	m_addrRemote.sin_addr.s_addr=inet_addr(targetip) ; 
 
	// Create the socket for data sending 
 
	if ((m_sockReceiver=socket(AF_INET,SOCK_DGRAM,0)) 
		==INVALID_SOCKET) 
	{ 
 
#ifdef _DEBUG 
 
 		printf("run time error:") ; 
 		printf("cann't create receiver (socket).\n") ; 
 
#endif 
 
		OnInitComplete(SOCKET_CALL_FAILD) ; 
 
		return SOCKET_CALL_FAILD ; 
	} 
 
	// Set port for receiver 
 
	m_addrLocal.sin_family=AF_INET ; 
	m_addrLocal.sin_port=htons((short)localport) ; 
	m_addrLocal.sin_addr.s_addr=htonl(INADDR_ANY) ; 
 
	if (bind(m_sockReceiver,(SOCKADDR*)&m_addrLocal, 
		sizeof(m_addrLocal))==SOCKET_ERROR) 
	{ 
 
#ifdef _DEBUG 
 
 		printf("run time error:") ; 
 		printf("cann't create receiver (bind).\n") ; 
 
#endif 
 
		OnInitComplete(BIND_CALL_FAILD) ; 
 
		return BIND_CALL_FAILD ; 
	} 
 
 
	if (m_wm==auto_receive) 
	{ 
 
		// Start the thread(task) for data receiving 
 
#ifdef WIN32 
 
		m_hThread = CreateThread(NULL,NULL, 
			(LPTHREAD_START_ROUTINE)recvsrv,this,NULL,NULL) ; 
 
#ifdef _DEBUG 
 
		printf("threadid 0x%x loaded.\n",m_hThread) ; 
 
#endif // _DEBUG 
 
		if (m_hThread==NULL) 
		{ 
 
#ifdef _DEBUG 
 
 			printf("run time error:") ; 
 			printf("cann't start receiver (thread).\n") ; 
 
#endif // _DEBUG 
 
			OnInitComplete(THREAD_CALL_FAILD) ; 
 
			return THREAD_CALL_FAILD ; 
		} 
 
#endif // WIN32 
 
#ifdef VXWORKS 0 
 
		m_hTask = taskSpawn("recvsrv1",60,VX_FP_TASK, 
			1024*40,(FUNCPTR)recvsrv,(int)this, 
			0,0,0,0,0,0,0,0,0 
			) ; 
 
		if (m_hTask==ERROR) 
		{ 
 
#ifdef _DEBUG 
 
 			printf("run time error:") ; 
 			printf("cann't start receiver (task).\n") ; 
 
#endif // _DEBUG 
 
			OnInitComplete(THREAD_CALL_FAILD) ; 
 
			return THREAD_CALL_FAILD ; 
		} 
		else 
		{ 
 
#ifdef _DEBUG 
 
			printf("taskid 0x%x spawned.\n",m_hTask) ; 
 
#endif // _DEBUG 
 
		} 
 
 
#endif // VXWORKS 
 
	} 
 
	// All the sockets and threads are loaded 
 
	m_bReady = true ; 
	OnInitComplete(OK) ; 
 
	return OK ; 
} 
 
unsigned long CUdpSocket::recvsrv(void * pt) 
{ 
 
	CUdpSocket * pthis = (CUdpSocket *)pt ; 
	static char szBuf[4096] ; 
	int iSockAddrSize = sizeof(sockaddr_in) ; 
	static char szIpAddr[16] ; 
 
	// Receive data form network. 
 
	// When any data arrive, call OnBeforReceive() and 
	// OnReceive to dispose the data. 
 
	while (true) 
	{ 
		FD_ZERO(&(pthis->m_fdSel)) ; 
		FD_SET((unsigned)pthis->m_sockReceiver, 
			&(pthis->m_fdSel)) ; 
		 
#ifdef _DEBUG 
 
		// printf("waiting for incoming message.\n") ; 
 
#endif // _DEBUG 
 
		if (!select(FD_SETSIZE,&(pthis->m_fdSel), 
			NULL,NULL,&(pthis->m_tvDelay))) 
		{ 
 
#ifdef VXWORKS 
 
			taskDelay(1) ; 
 
#endif // VXWORKS 
 
			continue ; 
		} 
 
		memset(szBuf,0,4096) ; 
		memset(&(pthis->m_addrRecv),0, 
			sizeof(sockaddr_in)) ; 
 
		int iRet=recvfrom 
			(pthis->m_sockReceiver, 
			szBuf,4096,0, 
			(SOCKADDR*)&(pthis->m_addrRecv), 
			&iSockAddrSize 
			) ; 
 
		strcpy(szIpAddr,inet_ntoa 
			(pthis->m_addrRecv.sin_addr)) ; 
 
		if (iRet!=SOCKET_ERROR) 
		{ 
			pthis->OnBeforeReceive 
				(iRet,szBuf,&(pthis->m_addrRecv)) ; 
 
			pthis->OnReceive 
				(iRet,szBuf,&(pthis->m_addrRecv)) ; 
		} 
	} 
 
} 
 
void CUdpSocket::SetRemoteAddr(const char * targetip,int port) 
{ 
	// Set port and remote host for sender 
 
	m_addrRemote.sin_port=htons((short)port) ; 
	m_addrRemote.sin_addr.s_addr=inet_addr(targetip) ; 
} 
 
const char * CUdpSocket::GetRemoteIp() 
{ 
	static char szIp[16] ; 
 
	strcpy(szIp,inet_ntoa(m_addrRemote.sin_addr)) ; 
 
	return szIp ; 
} 
 
int CUdpSocket::GetRemotePort() 
{ 
	return m_addrRemote.sin_port ; 
} 
 
int CUdpSocket::GetLocalPort() 
{ 
	return m_addrRemote.sin_port ; 
} 
 
STATUS CUdpSocket::Send 
	(int buflen,void * buf,sockaddr_in * addr) 
{ 
	// The simple version for sendto(...) 
 
	int nBytesSent ; 
 
	if (!m_bReady) return NOT_INITIALIZED ; 
 
	if (addr==NULL) 
		addr = &m_addrRemote ; 
 
	OnBeforeSend(buflen,buf) ; 
 
	nBytesSent = sendto 
		(m_sockSender,(char *)buf,buflen,0, 
		(SOCKADDR*)addr,sizeof(SOCKADDR) 
		) ; 
 
	OnSendComplete(nBytesSent) ; 
 
	return nBytesSent ; 
} 
 
STATUS CUdpSocket::Recv(int buflen,void * buf, 
						int timeout,sockaddr_in * addr) 
{ 
	int iSockAddrSize = sizeof(sockaddr_in) ; 
	int iRet = NULL ; 
	timeval tv ; 
 
	// Receive data form network. 
 
	if (timeout!=0) 
	{ 
 
		FD_ZERO(&(m_fdSel)) ; 
		FD_SET((unsigned)m_sockReceiver,&m_fdSel) ; 
 
		tv.tv_sec = timeout/1000 ; 
		tv.tv_usec = (timeout%1000)*1000 ; 
		 
#ifdef _DEBUG 
 
		printf("waiting for incoming message.\n") ; 
 
#endif // _DEBUG 
 
		if (!select(FD_SETSIZE,&m_fdSel, 
			NULL,NULL,&tv)) 
			return RECV_TIMEOUT ; 
 
	} 
 
	memset(buf,0,buflen) ; 
 
	if (addr==NULL) 
	{ 
		memset(&m_addrRecv,0,sizeof(sockaddr_in)) ; 
		addr = &m_addrRecv ; 
	} 
	else 
	{ 
		memset(addr,0,sizeof(sockaddr_in)) ; 
	} 
 
	iRet = recvfrom // Receive data gram 
		(m_sockReceiver, 
		(char *)buf,buflen,0, 
		(SOCKADDR*)addr,&iSockAddrSize 
		) ; 
 
	return iRet ; 
 
} 
 
STATUS CUdpSocket::SetSenderBufferSize(int size) 
{ 
	return setsockopt 
		(m_sockSender,SOL_SOCKET, 
		SO_SNDBUF,(char *)&size,sizeof(int) 
		) ; 
} 
 
int CUdpSocket::GetSenderBufferSize() 
{ 
	int size,n ; 
 
	getsockopt 
		(m_sockSender,SOL_SOCKET, 
		SO_SNDBUF,(char *)&size,&n 
		) ; 
 
	return size ; 
} 
 
STATUS CUdpSocket::SetReceiverBufferSize(int size) 
{ 
	return setsockopt 
		(m_sockReceiver,SOL_SOCKET, 
		SO_SNDBUF,(char *)&size,sizeof(int) 
		) ; 
} 
 
int CUdpSocket::GetReceiverBufferSize() 
{ 
	int size,n ; 
 
	getsockopt 
		(m_sockReceiver,SOL_SOCKET, 
		SO_SNDBUF,(char *)&size,&n 
		) ; 
 
	return size ; 
} 
 
int CUdpSocket::GetSenderSocket() 
{ 
	return m_sockSender ; 
} 
 
int CUdpSocket::GetReceiverSocket() 
{ 
	return m_sockReceiver ; 
} 
 
CUdpSocket::~CUdpSocket() 
{ 
 
#ifdef WIN32 
 
#ifdef _DEBUG 
 
	BOOL bThreadTerminated = FALSE ; 
 
#endif // _DEBUG 
 
	if (NULL!=m_sockSender&& 
		INVALID_SOCKET!=m_sockSender) 
		closesocket(m_sockSender) ; 
 
	if (NULL!=m_sockReceiver&& 
		INVALID_SOCKET!=m_sockReceiver) 
		closesocket(m_sockReceiver) ; 
 
	WSACleanup() ; 
 
	// Terminate the recvsrv thread 
 
#ifdef _DEBUG 
 
	bThreadTerminated = TerminateThread 
		((HANDLE)m_hThread,0) ; 
 
	CloseHandle(m_hThread) ; 
 
	if (bThreadTerminated) 
		printf("thread 0x%x terminated.\n",m_hThread) ; 
 
#else 
 
	TerminateThread((HANDLE)m_hThread,0) ; 
 
#endif // _DEBUG 
 
#endif // _WIN32 
 
#ifdef VXWORKS 
 
#ifdef _DEBUG 
 
	bool bTaskDeleted = false ; 
 
#endif // _DEBUG 
 
	if (NULL!=m_sockSender&& 
		INVALID_SOCKET!=m_sockSender) 
	{ 
		shutdown(m_sockSender,2) ; 
		close(m_sockSender) ; 
	} 
 
	if (NULL!=m_sockReceiver&& 
		INVALID_SOCKET!=m_sockReceiver) 
	{ 
		shutdown(m_sockReceiver,2) ; 
		close(m_sockReceiver) ; 
	} 
 
#ifdef _DEBUG 
 
	bTaskDeleted = taskDelete(m_hTask) ; 
 
	if (bTaskDeleted!=ERROR) 
		printf("task 0x%x deleted.\n",m_hTask) ; 
 
#else 
 
	taskDelete(m_hTask) ; 
 
#endif // _DEBUG 
 
#endif // VXWORKS 
 
} 
 
// Our overridable functions. 
 
// In the base class "CUdpSocket", the functions do nothing 
 
void CUdpSocket::OnInitComplete(STATUS status) 
{ 
 
#ifdef _DEBUG 
 
	printf("OnInitComplete(%d)\n",status) ; 
 
#endif 
 
} 
 
void CUdpSocket::OnBeforeSend(int buflen,void * buf) 
{ 
 
#ifdef _DEBUG 
 
	printf("OnBeforeSend(%d,...)\n",buflen) ; 
 
#endif 
 
} 
 
void CUdpSocket::OnSendComplete(STATUS status) 
{ 
 
#ifdef _DEBUG 
 
	printf("OnSendComplete(%d)\n",status) ; 
 
#endif 
 
} 
 
void CUdpSocket::OnBeforeReceive 
	(int buflen,void * buf,sockaddr_in * addr) 
{ 
 
#ifdef _DEBUG 
 
	printf("OnBeforeReceive(%d,...)\n",buflen) ; 
 
#endif 
 
} 
 
void CUdpSocket::OnReceive 
	(int buflen,void * buf,sockaddr_in * addr) 
{ 
 
#ifdef _DEBUG 
 
	printf("OnReceive(%d,...)\n",buflen) ; 
 
#endif 
 
} 
 
// End of the file