From d42a6937e7b9eba39de3c7d8edc975499d1f43ff Mon Sep 17 00:00:00 2001 From: fcolin Date: Thu, 1 Feb 2007 13:04:49 +0000 Subject: Utilisateur : Fcolin Date : 16/06/00 Heure : 10:14 Créé (vss 1) --- Ivy/ThreadedSocket.cxx | 439 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 Ivy/ThreadedSocket.cxx (limited to 'Ivy') diff --git a/Ivy/ThreadedSocket.cxx b/Ivy/ThreadedSocket.cxx new file mode 100644 index 0000000..f00e6f5 --- /dev/null +++ b/Ivy/ThreadedSocket.cxx @@ -0,0 +1,439 @@ +// ThreadedSocket.cpp: implementation of the CThreadedSocket class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include + +#include "ThreadedSocket.h" + + +// Class CThreadedSocketException +//IMPLEMENT_DYNAMIC(CThreadedSocketException, CException) + +CThreadedSocketException::CThreadedSocketException(char* pchMessage) +{ + m_strMessage = pchMessage; + m_nError = WSAGetLastError(); +} + +bool CThreadedSocketException::GetErrorMessage(string & lpstrError, UINT nMaxError, + PUINT pnHelpContext /*= NULL*/) +{ + lpstrError = m_strMessage; + lpstrError += "error"; + if(m_nError != 0) + { + lpstrError += " #"; + lpstrError += m_nError; + } + return true; +} + +//IMPLEMENT_DYNAMIC(CThreadedSocket, CObject) + +bool CThreadedSocket::Initialized = false; + +void CThreadedSocket::Init() +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD( 2, 2 ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + return; + } + Initialized = true; +} + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CThreadedSocket::CThreadedSocket() +{ + if ( ! Initialized ) Init(); + + m_hSocket = INVALID_SOCKET; + h_thread = NULL; + // Create events to wait on + // for receivier part + m_hEvent[0] = WSACreateEvent(); + if ( m_hEvent[0] == WSA_INVALID_EVENT ) + { + TRACE( "CThreadedSocketException(WSACreateEvent )\n"); + throw( new CThreadedSocketException( "WSACreateEvent" )); + } + // for transmitter part + m_hEvent[1] = WSACreateEvent(); + if ( m_hEvent[1] == WSA_INVALID_EVENT ) + { + TRACE( "CThreadedSocketException(WSACreateEvent )\n"); + throw( new CThreadedSocketException( "WSACreateEvent" )); + } +} + +CThreadedSocket::~CThreadedSocket() +{ + if (m_hSocket != INVALID_SOCKET) + Close(); + //if ( thread ) // On fait de l'auto delete mais dans le cas de terminaison anormale l'object reste ????!!! + // delete thread; + WSACloseEvent( m_hEvent[0] ); + WSACloseEvent( m_hEvent[1] ); +} +void CThreadedSocket::Create(UINT nSocketPort, int nSocketType, + long lEvent, const char * lpszSocketAddress) +{ + Socket(nSocketType, lEvent); + Bind(nSocketPort,lpszSocketAddress); +} + +///////////////////////////////////////////////////////////////////////////// +// CThreadedSocket Attributes + + + +void CThreadedSocket::GetPeerName(string & rPeerAddress, UINT& rPeerPort) +{ + SOCKADDR_IN sockAddr; + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); + rPeerPort = ntohs(sockAddr.sin_port); + rPeerAddress = inet_ntoa(sockAddr.sin_addr); +} + +void CThreadedSocket::GetSockName(string & rSocketAddress, UINT& rSocketPort) +{ + SOCKADDR_IN sockAddr; + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen); + rSocketPort = ntohs(sockAddr.sin_port); + rSocketAddress = inet_ntoa(sockAddr.sin_addr); +} + +///////////////////////////////////////////////////////////////////////////// +// CAscynSocket Operations + +void CThreadedSocket::Accept(CThreadedSocket& rConnectedSocket, + SOCKADDR* lpSockAddr, int* lpSockAddrLen) +{ + assert(rConnectedSocket.m_hSocket == INVALID_SOCKET); + + + SOCKET hTemp = accept(m_hSocket, lpSockAddr, lpSockAddrLen); + + if (hTemp == INVALID_SOCKET) + { + rConnectedSocket.m_hSocket = INVALID_SOCKET; + throw( new CThreadedSocketException( "accept" ) ); + } + else + { + rConnectedSocket.m_hSocket = hTemp; + rConnectedSocket.StartListener(m_EventMask); + } +} + +void CThreadedSocket::Bind(UINT nSocketPort, const char * lpszSocketAddress) +{ + + SOCKADDR_IN sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + + sockAddr.sin_family = AF_INET; + + if (lpszSocketAddress == NULL) + sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + DWORD lResult = inet_addr(lpszSocketAddress); + if (lResult == INADDR_NONE) + { + WSASetLastError(WSAEINVAL); + throw( new CThreadedSocketException( "bind" ) ); + } + sockAddr.sin_addr.s_addr = lResult; + } + + sockAddr.sin_port = htons((u_short)nSocketPort); + + Bind((SOCKADDR*)&sockAddr, sizeof(sockAddr)); +} + +void CThreadedSocket::Close() +{ + if (m_hSocket != INVALID_SOCKET) + { + AsyncSelect(0); + assert(SOCKET_ERROR != closesocket(m_hSocket)); + m_hSocket = INVALID_SOCKET; + //WSASetEvent( m_hEventObject ); + } +} + +bool CThreadedSocket::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen) +{ + if ( !connect(m_hSocket, lpSockAddr, nSockAddrLen) ) + { + DWORD err = WSAGetLastError(); + if ( err == 0 ) return TRUE; + TRACE( "***************************************Error connect %d\n", err); + if ( err != WSAEWOULDBLOCK ) + return FALSE; + // Wait for connection to complete + TRACE( "***************************************Waiting for connection to complete\n"); + err = WSAWaitForMultipleEvents( 1, m_hEvent, FALSE, WSA_INFINITE, TRUE); + //TRACE( "Thread socket %d wait return %d\n", m_hSocket, err ); + if ( err == WSA_WAIT_FAILED ) + { + return FALSE; + } + + return TRUE; + } + return TRUE; +} + +bool CThreadedSocket::Connect(const char * lpszHostAddress, UINT nHostPort) +{ + + assert(lpszHostAddress != NULL); + + SOCKADDR_IN sockAddr; + memset(&sockAddr,0,sizeof(sockAddr)); + + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress); + + if (sockAddr.sin_addr.s_addr == INADDR_NONE) + { + LPHOSTENT lphost; + lphost = gethostbyname(lpszHostAddress); + if (lphost != NULL) + sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr; + else + { + WSASetLastError(WSAEINVAL); + return FALSE; + } + } + + sockAddr.sin_port = htons((u_short)nHostPort); + + return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr)); +} + +int CThreadedSocket::Receive(void* lpBuf, int nBufLen, int nFlags) +{ + int lg = recv(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags); + if ( lg == SOCKET_ERROR ) + throw( new CThreadedSocketException( "recv" ) ); + return lg; +} + +int CThreadedSocket::ReceiveFrom(void* lpBuf, int nBufLen, string & rSocketAddress, UINT& rSocketPort, int nFlags) +{ + SOCKADDR_IN sockAddr; + + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + int nResult = ReceiveFrom(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, &nSockAddrLen, nFlags); + rSocketPort = ntohs(sockAddr.sin_port); + rSocketAddress = inet_ntoa(sockAddr.sin_addr); + + return nResult; +} + +void CThreadedSocket::Send(const void* lpBuf, int nBufLen, int nFlags) +{ + if ( send(m_hSocket, (LPSTR)lpBuf, nBufLen, nFlags) != nBufLen ) + throw( new CThreadedSocketException( "send" ) ); +} + +void CThreadedSocket::SendTo(const void* lpBuf, int nBufLen, UINT nHostPort, const char * lpszHostAddress, int nFlags) +{ + SOCKADDR_IN sockAddr; + + memset(&sockAddr,0,sizeof(sockAddr)); + + sockAddr.sin_family = AF_INET; + + if (lpszHostAddress == NULL) + sockAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST); + else + { + sockAddr.sin_addr.s_addr = inet_addr(lpszHostAddress); + if (sockAddr.sin_addr.s_addr == INADDR_NONE) + { + LPHOSTENT lphost; + lphost = gethostbyname(lpszHostAddress); + if (lphost != NULL) + sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr; + else + { + WSASetLastError(WSAEINVAL); + throw( new CThreadedSocketException( "SendTo" )); + return; + } + } + } + + sockAddr.sin_port = htons((u_short)nHostPort); + + SendTo(lpBuf, nBufLen, (SOCKADDR*)&sockAddr, sizeof(sockAddr), nFlags); +} +void CThreadedSocket::AsyncSelect(long lEvent) +{ + assert(m_hSocket != INVALID_SOCKET); + if ( WSAEventSelect(m_hSocket, m_hEvent[0], lEvent) ) + throw( new CThreadedSocketException( "WSAEventSelect" )); +} +///////////////////////////////////////////////////////////////////////////// +// CThreadedSocket Overridable callbacks +void CThreadedSocket::OnWakeup() +{ +} +void CThreadedSocket::OnReceive(int /*nErrorCode*/) +{ +} + +void CThreadedSocket::OnSend(int /*nErrorCode*/) +{ +} + +void CThreadedSocket::OnOutOfBandData(int /*nErrorCode*/) +{ +} + +void CThreadedSocket::OnAccept(int /*nErrorCode*/) +{ +} + +void CThreadedSocket::OnConnect(int /*nErrorCode*/) +{ +} + +void CThreadedSocket::OnClose(int /*nErrorCode*/) +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CThreadedSocket Implementation + + +void CThreadedSocket::Socket(int nSocketType, long lEvent, int nProtocolType, int nAddressFormat) +{ + assert(m_hSocket == INVALID_SOCKET); + + m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType); +// m_hSocket = WSASocket ( nAddressFormat, nSocketType,nProtocolType, NULL, 0, 0 ); + + + if (m_hSocket == INVALID_SOCKET) + { + throw( new CThreadedSocketException( "socket" )); + } + StartListener(lEvent); + +} + +void CThreadedSocket::StartListener(long lEvent) +{ + m_EventMask = lEvent; + h_thread = CreateThread(NULL,0,SocketThreadProc, this, 0, &thread_id); + if ( ! h_thread ) + throw( new CThreadedSocketException( "socket listener" )); +} +// Implementation +DWORD WINAPI CThreadedSocket::SocketThreadProc( LPVOID pParam ) +{ + CThreadedSocket* pObject = (CThreadedSocket*)pParam; + + if (pObject == NULL ) + { + throw( new CThreadedSocketException( "bad socket proc" )); + return -1; // if pObject is not valid + } + + return pObject->SocketThread(); +} + +UINT CThreadedSocket::SocketThread( ) +{ + DWORD err; + WSANETWORKEVENTS NetworkEvents; + + AsyncSelect(m_EventMask) ; + while ( m_hSocket != INVALID_SOCKET ) + { + err = WSAWaitForMultipleEvents( 2, m_hEvent, FALSE, WSA_INFINITE, TRUE); + switch ( err ) + { + case WSA_WAIT_FAILED: + TRACE( "CThreadedSocketException(WSAWaitForMultipleEvents )\n"); + throw( new CThreadedSocketException( "WSAWaitForMultipleEvents" )); + return err; + break; + case WSA_WAIT_EVENT_0: + + NetworkEvents.lNetworkEvents=0; + + if ( WSAEnumNetworkEvents ( m_hSocket, m_hEvent[0], &NetworkEvents )) + { + TRACE( "CThreadedSocketException(WSAEnumNetworkEvents )\n"); + throw( new CThreadedSocketException( "WSAEnumNetworkEvents" )); + return -1; + } + + + if ( NetworkEvents.lNetworkEvents & FD_READ ) + OnReceive(NetworkEvents.iErrorCode[ FD_READ_BIT ]); + + if ( NetworkEvents.lNetworkEvents & FD_WRITE ) + OnSend( NetworkEvents.iErrorCode[ FD_WRITE_BIT ] ); + + if ( NetworkEvents.lNetworkEvents & FD_ACCEPT ) + OnAccept( NetworkEvents.iErrorCode[ FD_ACCEPT_BIT ] ); + + + if ( NetworkEvents.lNetworkEvents & FD_CONNECT ) + OnConnect( NetworkEvents.iErrorCode[ FD_CONNECT_BIT ] ); + + if ( NetworkEvents.lNetworkEvents & FD_OOB ) + OnOutOfBandData( NetworkEvents.iErrorCode[ FD_OOB_BIT ] ); + + if ( NetworkEvents.lNetworkEvents & FD_CLOSE ) + { + OnClose( NetworkEvents.iErrorCode[ FD_CLOSE_BIT ] ); + } + + break; + case WSA_WAIT_EVENT_0 +1 : + if ( m_hSocket != INVALID_SOCKET ) + { + OnWakeup(); + } + // else Close by other Thread do silent terminaison + WSAResetEvent( m_hEvent[1] ); + + break; + default: + TRACE( "CThreadedSocket::SocketThread Unhandled Events !\n"); + break; + } + } + Close(); + h_thread = NULL; + return 0; +} -- cgit v1.1