#include "Socket.h" #include "Common.h" #include "ExceptionHandler.h" #ifdef DEBUG #include "Common.h" #include "Configuration.h" #endif #pragma comment(lib,"wsock32.lib") #ifndef MSG_WAITALL // غير متأكد من السبب في ان يتم ذلك #define MSG_WAITALL 0x08 #endif Socket::Socket( LPCSTR serverName, u16_t port ) : sock( INVALID_SOCKET ), listener( false ), currentPort( 0 ) { if( !ConnectToServer( serverName, port ) ) ExceptionHandler::Throw( L"Error Socket::ConnectToServer (%i)", iWsaError ); } Socket::Socket( SOCKET newSocket ) : listener( false ), currentPort( 0 ) { setSocket( newSocket ); } Socket::Socket( u16_t port ) : sock( INVALID_SOCKET ), listener( true ), currentPort( 0 ) { if( !CreateAsServer( port ) ) ExceptionHandler::Throw( L"Error Socket::CreateAsServer (%i)", iWsaError ); } Socket::Socket() : sock( INVALID_SOCKET ), listener( false ), currentPort( 0 ) { } Socket::~Socket() { Cleanup(); } void Socket::RecordError() { iWsaError = WSAGetLastError(); } bool Socket::WSAStartUp( WORD versionReq, LPWSADATA lpWsaData ) { WSADATA wsaData; if( !lpWsaData ) lpWsaData = &wsaData; if( WSAStartup( versionReq, lpWsaData ) ) return false; return true; } void Socket::setSocket( SOCKET newSocket ) { Cleanup(); sock = newSocket; listener = false; } SOCKET Socket::ExportSocket() { SOCKET tmpRet = sock; sock = INVALID_SOCKET; return tmpRet; } SOCKET Socket::getSocket() { return sock; } void Socket::Cleanup() { if( sock != INVALID_SOCKET ) closesocket( sock ); sock = INVALID_SOCKET; } bool Socket::isReadReady( DWORD dwSecondsToWait, DWORD dwMicrosecondsToWait ) { timeval timeout = { dwSecondsToWait, dwMicrosecondsToWait }; int nfds; fd_set read_fds; FD_ZERO( &read_fds ); FD_SET( sock, &read_fds ); nfds = select( 0, &read_fds, NULL, NULL, &timeout ); if( nfds < 0 ) { RecordError(); ExceptionHandler::Throw( L"Error Socket::select (%i)", iWsaError ); } return (bool)(nfds > 0); } SOCKET Socket::getClientSocket( DWORD dwSecondsToWait, DWORD dwMicrosecondsToWait, sockaddr_in* newAddr ) { if( !isReadReady( dwSecondsToWait, dwMicrosecondsToWait ) ) return INVALID_SOCKET; sockaddr_in* newAddrPtr; sockaddr_in lAddr; newAddrPtr = newAddr ? newAddr : &lAddr; int addrLen = sizeof( sockaddr_in ); return accept( sock, (sockaddr*)newAddrPtr, &addrLen ); } bool Socket::Read( LPVOID inBuffer, DWORD maxLen, LPDWORD nbRead, bool flush ) { int nBytes = recv( sock, (char*)inBuffer, maxLen, flush ? MSG_WAITALL : 0 ); if( nBytes <= 0 ) { RecordError(); return false; } if( nbRead ) *nbRead = (DWORD)nBytes; else if( flush && (DWORD)nBytes != maxLen ) return false; // If our option was to flush and we couldn't, then error return true; } bool Socket::Write( LPVOID outBuffer, DWORD maxLen, LPDWORD nbWritten, bool flush ) { DWORD totalWritten = 0; do { int nBytes = send( sock, (char*)outBuffer + totalWritten, maxLen - totalWritten, 0 ); if( nBytes <= 0 ) { RecordError(); return false; } totalWritten += (DWORD)nBytes; } while( flush && totalWritten < maxLen ); if( nbWritten ) *nbWritten = totalWritten; return true; } bool Socket::Close() { Cleanup(); return true; } bool Socket::CreateAsServer( u16_t port ) { Cleanup(); sockaddr_in myAddr; listener = true; currentPort = port; sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if( sock == INVALID_SOCKET ) { RecordError(); return false; } myAddr.sin_addr.S_un.S_addr = INADDR_ANY; myAddr.sin_family = AF_INET; myAddr.sin_port = htons( port ); memset( &myAddr.sin_zero, 0, sizeof( myAddr.sin_zero ) ); if( bind( sock, (sockaddr*)&myAddr, sizeof(myAddr) ) == SOCKET_ERROR ) { RecordError(); Cleanup(); return false; } if( listen( sock, SOMAXCONN ) == SOCKET_ERROR ) { RecordError(); Cleanup(); return false; } return true; } bool Socket::ConnectToServer( LPCSTR serverName, u16_t port ) { Cleanup(); listener = false; currentPort = port; sockaddr_in theirAddr; hostent* host; host = gethostbyname( serverName ); if( !host ) { RecordError(); return false; } sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if( sock == INVALID_SOCKET ) { RecordError(); return false; } theirAddr.sin_addr.S_un.S_addr = inet_addr( inet_ntoa( *(in_addr*)host->h_addr ) ); theirAddr.sin_family = AF_INET; theirAddr.sin_port = htons( port ); memset( &theirAddr.sin_zero, 0, sizeof( theirAddr.sin_zero ) ); if( connect( sock, (sockaddr*)&theirAddr, sizeof( theirAddr ) ) == SOCKET_ERROR ) { RecordError(); Cleanup(); return false; } return true; }