00001 //***************************************************************************** 00002 // project : ANALYTICA Class Library 00003 // part : Communication class for simple TCP/IP 00004 // file name : TCPIPComm.h 00005 // version : 1.2 00006 // author : Udo Weber 00007 // platform : MS VC++ 6.0 00008 // 00009 //----------------------------------------------------------------------------- 00010 // Description: 00011 // ============= 00012 // implementation of the class CTCPIPComm to encapsulate simple TCP/IP 00013 // communications 00014 // Contains the main part of the communication classes. Organizes the 00015 // handling of the three lower classes CTCPIPCommConnect, CTCPIPCommRecv and 00016 // CTCPIPCommSend. 00017 // 00018 //----------------------------------------------------------------------------- 00019 // Revisionhistory: 00020 // 03.07.2001 ASc Deferred Initialization added 00021 // 20.07.1998 UWe Some bug fixes 00022 // 20.04.1998 UWe first version 00023 //***************************************************************************** 00024 00025 //---- includes --------------------------------------------------------------- 00026 #include "stdafx.h" 00027 00028 #include "TCPIPComm.h" 00029 00030 00031 //---- defines/const ---------------------------------------------------------- 00032 00033 00034 00035 //---- classes ----------------------------------------------------------------- 00036 00037 00038 //****************************************************************************** 00039 // Methods of class 'CTCPIPComm' 00040 //****************************************************************************** 00041 00042 // Static attributes and operations 00043 00044 int CTCPIPComm::m_NumOfInstances = 0; 00045 //SOCKET CTCPIPComm::m_PassiveSocket = INVALID_SOCKET; 00046 bool CTCPIPComm::m_bArrayUsed[] = { false, false }; 00047 SOCKADDR_IN CTCPIPComm::m_ArrayRemoteAddr[]= { 0, 0 }; 00048 SOCKET CTCPIPComm::m_ArrayPassiveSocket[]= { INVALID_SOCKET, INVALID_SOCKET }; 00049 00050 00051 //------------------------------------------------------------------------------ 00052 // Description: 00053 // Constructs the class CTCPIPComm and creates a new communication instance. 00054 // A new instance is necessary for every communication partner 00055 // 00056 // Input: 00057 // TCPport : Port number to be used for the communication 00058 // pIPAddress : NULL terminated string containing IP Address or Name of partner 00059 // PassiveConnection: true if awaiting the connection from the partner 00060 // MaxSendDataLen : Maximum length for sending messages 00061 // MaxRecvDataLen : Maximum length for receiving messages 00062 // 00063 // Output: ---- 00064 // 00065 // Return: ---- 00066 // 00067 //------------------------------------------------------------------------------ 00068 CTCPIPComm::CTCPIPComm( const short TCPport, 00069 const char *pIPAddress, 00070 const bool PassiveConnection, 00071 const long MaxSendBufferLen, 00072 const long MaxRecvBufferLen ) 00073 : CTCPIPCommReceive( -1 ), 00074 CTCPIPCommSend( -1 ), 00075 CTCPIPCommConnect() 00076 { 00077 m_bInitialized = false; 00078 m_bTerminating = false; 00079 Initialize( TCPport, pIPAddress, PassiveConnection, MaxSendBufferLen, MaxRecvBufferLen ); 00080 } 00081 00082 //------------------------------------------------------------------------------ 00083 // Description: 00084 // Constructs the class CTCPIPComm. The communication instance must bei created by a 00085 // call to the Initialize function (only available in a derived class) 00086 // 00087 // Input: ---- 00088 // 00089 // Output: ---- 00090 // 00091 // Return: ---- 00092 // 00093 //------------------------------------------------------------------------------ 00094 CTCPIPComm::CTCPIPComm( void ) 00095 : CTCPIPCommReceive( -1 ), 00096 CTCPIPCommSend( -1 ), 00097 CTCPIPCommConnect() 00098 { 00099 m_bInitialized = false; 00100 } 00101 00102 //------------------------------------------------------------------------------ 00103 // Description: 00104 // Initialization-Routine for object construction. 00105 // 00106 // Input: 00107 // TCPport : Port number to be used for the communication 00108 // pIPAddress : NULL terminated string containing IP Address or Name of partner 00109 // PassiveConnection: true if awaiting the connection from the partner 00110 // MaxSendDataLen : Maximum length for sending messages 00111 // MaxRecvDataLen : Maximum length for receiving messages 00112 // 00113 // Output: ---- 00114 // 00115 // Return: ---- 00116 // 00117 //------------------------------------------------------------------------------ 00118 void CTCPIPComm::Initialize( const short TCPport, 00119 const char *pIPAddress, 00120 const bool PassiveConnection, 00121 const long MaxSendDataLen, 00122 const long MaxRecvDataLen ) 00123 { 00124 bool SocketFound; 00125 int i; 00126 00127 if ( m_bInitialized == true ) 00128 { 00129 return; 00130 } 00131 00132 m_bInitialized = true; 00133 00134 // Initialize Receive and Send-classes 00135 CTCPIPCommReceive::InitializeClass( MaxRecvDataLen ); 00136 CTCPIPCommSend::InitializeClass( MaxSendDataLen ); 00137 00138 m_LineConnected = false; 00139 m_LastSocketError = 0; 00140 m_PassiveConnection = PassiveConnection; 00141 m_PassiveSocket = INVALID_SOCKET; 00142 00143 if ( m_NumOfInstances++ == 0 ) 00144 { 00145 // If the first instance of this class is created, the 00146 // socket for the passive connections (await function) 00147 // has to be created. PXROS does not support more than 00148 // one socket for the same TCP/IP address. 00149 WSADATA WsaData; 00150 if ( WSAStartup( 0x0101, &WsaData ) == SOCKET_ERROR ) 00151 { 00152 m_LastSocketError = GetLastError(); 00153 return; 00154 } 00155 } 00156 00157 if ( PassiveConnection ) 00158 { 00159 00160 m_RemoteAddr = ConvTCPAddrToSocketAddr( TCPport, pIPAddress ); 00161 00162 for ( i = 0, SocketFound = false; i < MAX_DIF_ADDR; i++ ) 00163 if ( m_bArrayUsed[ i ] ) 00164 if ( memcmp( &m_RemoteAddr, &m_ArrayRemoteAddr[ i ], sizeof( m_RemoteAddr ) ) == 0 ) 00165 { 00166 SocketFound = true; 00167 break; 00168 } 00169 00170 if ( SocketFound ) 00171 m_PassiveSocket = m_ArrayPassiveSocket[ i ]; 00172 else 00173 { 00174 for ( i = 0; i < MAX_DIF_ADDR; i++ ) 00175 if ( ! m_bArrayUsed[ i ] ) 00176 { 00177 m_PassiveSocket = socket( AF_INET, SOCK_STREAM, 0 ); 00178 bind( m_PassiveSocket, (PSOCKADDR) &m_RemoteAddr, sizeof( m_RemoteAddr ) ); 00179 listen( m_PassiveSocket, SOMAXCONN ); 00180 m_ArrayPassiveSocket[i] = m_PassiveSocket; 00181 m_ArrayRemoteAddr[i] = m_RemoteAddr; 00182 m_bArrayUsed[i] = true; 00183 break; 00184 } 00185 } 00186 00187 } 00188 00189 // Initialize the Connect class 00190 CTCPIPCommConnect::Initialize( TCPport, pIPAddress, m_PassiveConnection ); 00191 } 00192 00193 //------------------------------------------------------------------------------ 00194 // Description: 00195 // Destructs the CTCPIPComm class 00196 // 00197 // Input: ---- 00198 // 00199 // Output: ---- 00200 // 00201 // Return: ---- 00202 // 00203 //------------------------------------------------------------------------------ 00204 CTCPIPComm::~CTCPIPComm() 00205 { 00206 m_bTerminating = true; 00207 00208 if ( --m_NumOfInstances == 0 ) 00209 { 00210 // Attention !!! 00211 // WSACleanup should be called after last instance of CTCPIPComm is deleted 00212 //WSACleanup(); 00213 } 00214 00215 // close the global passive socket --> All threads waiting in the "accept" call 00216 // will be released 00217 if ( m_PassiveSocket != INVALID_SOCKET ) 00218 { 00219 SOCKET TmpSocket = m_PassiveSocket; 00220 00221 m_PassiveSocket = INVALID_SOCKET; 00222 closesocket( TmpSocket ); 00223 00224 if ( m_NumOfInstances > 0 ) 00225 { 00226 // if other instances still exists create again the socket for the passive 00227 // connections. 00228 m_PassiveSocket = socket( AF_INET, SOCK_STREAM, 0 ); 00229 bind( m_PassiveSocket, (PSOCKADDR) &m_RemoteAddr, sizeof( m_RemoteAddr ) ); 00230 listen( m_PassiveSocket, SOMAXCONN ); 00231 } 00232 } 00233 00234 // signal the threads Receive/Send to terminate and wait for their termination 00235 CTCPIPCommReceive::Terminating( true ); 00236 CTCPIPCommSend::Terminating( false ); 00237 } 00238 00239 00240 00241 //------------------------------------------------------------------------------ 00242 // Description: 00243 // Try to establish the connection to the communication partner 00244 // 00245 // Input: ---- 00246 // 00247 // Output: ---- 00248 // 00249 // Return: true if function call successful 00250 // does not mean that the connection was connected --> ConnectIndication 00251 // 00252 //------------------------------------------------------------------------------ 00253 bool CTCPIPComm::ConnectRequest( void ) 00254 { 00255 return CTCPIPCommConnect::ConnectRequest( m_PassiveSocket ); 00256 } 00257 00258 00259 //------------------------------------------------------------------------------ 00260 // Description: 00261 // Transmits the given data to the communication partner 00262 // 00263 // Input: 00264 // pData : Pointer to the data to be sent 00265 // DataLen : Length of the data 00266 // 00267 // Output: ---- 00268 // 00269 // Return: ---- 00270 // 00271 //------------------------------------------------------------------------------ 00272 bool CTCPIPComm::Send( const void *pData, 00273 const long DataLen ) 00274 { 00275 if ( ! IsConnected() ) 00276 return FALSE; 00277 00278 return CTCPIPCommSend::Send( pData, DataLen ); 00279 } 00280 00281 00282 //------------------------------------------------------------------------------ 00283 // Description: 00284 // called from CTCPIPCommConnect in order to indicate the connect indication 00285 // 00286 // Input: ---- 00287 // 00288 // Output: ---- 00289 // 00290 // Return: ---- 00291 // 00292 //------------------------------------------------------------------------------ 00293 void CTCPIPComm::ConInd( void ) 00294 { 00295 m_LineConnected = TRUE; 00296 00297 // Send to the Receive and Send Thread the Init command in order 00298 // to tell them the socket handle to be used. 00299 CTCPIPCommSend::Initialize( GetSocket() ); 00300 CTCPIPCommReceive::Initialize( GetSocket() ); 00301 00302 // Signal to the user the connect indication 00303 ConnectIndication(); 00304 00305 // Signal to the receive thread that the receiving part can now be started 00306 // Attention: This has to be done after the "ConnectIndication" that the user 00307 // is informed first of the connected line. 00308 CTCPIPCommReceive::StartReceiving(); 00309 } 00310 00311 00312 //------------------------------------------------------------------------------ 00313 // Description: 00314 // called from CTCPIPCommConnect in order to indicate the disconnect indication 00315 // 00316 // Input: ---- 00317 // 00318 // Output: ---- 00319 // 00320 // Return: ---- 00321 // 00322 //------------------------------------------------------------------------------ 00323 void CTCPIPComm::DisInd( void ) 00324 { 00325 if ( m_LineConnected ) 00326 { 00327 m_LineConnected = FALSE; 00328 00329 CTCPIPCommConnect::DisconnectRequest(); 00330 } 00331 00332 00333 if ( ! m_bTerminating ) 00334 { 00335 // Inform "user" of this class always (to be able to try to connect again) 00336 DisconnectIndication(); 00337 } 00338 } 00339 00340 //------------------------------------------------------------------------------ 00341 // Description: 00342 // called by CTCPIPComRecv in order to indicate the disconnect indication 00343 // 00344 // Input: ---- 00345 // 00346 // Output: ---- 00347 // 00348 // Return: ---- 00349 // 00350 //------------------------------------------------------------------------------ 00351 void CTCPIPComm::RecvDisInd( void ) 00352 { 00353 DisInd(); 00354 } 00355 00356 //------------------------------------------------------------------------------ 00357 // Description: 00358 // called by CTCPIPComSend in order to indicate the disconnect indication 00359 // 00360 // Input: ---- 00361 // 00362 // Output: ---- 00363 // 00364 // Return: ---- 00365 // 00366 //------------------------------------------------------------------------------ 00367 void CTCPIPComm::SendDisInd( void ) 00368 { 00369 DisInd(); 00370 } 00371
1.3.7