Hauptseite   Klassenhierarchie   Datenstrukturen   Auflistung der Dateien   Datenstruktur-Elemente   Datei-Elemente  

RNSocket.cpp

gehe zur Dokumentation dieser Datei
00001 /***********************************************************************************/
00002 /** \file               RNSocket.cpp
00003 **  \brief              Implementation zur Klasse RNSocket
00004 *************************************************************************************
00005 **  Autor:              Christian Roesch
00006 **
00007 **  Erstelldatum:       27.03.2002
00008 **  letzte Aenderung:   31.03.2002
00009 *************************************************************************************
00010 **  Die Klasse RNSocket beitet eine Klasse zur Kapselung von WinSock.
00011 ************************************************************************************/
00012 
00013 
00014 // includes
00015 #include "RNSocket.h"
00016 
00017 bool    RNSocket::m_bSocketInitialized = false;
00018 WSADATA RNSocket::m_wsaData;
00019 
00020 // Methoden-Definitionen
00021 
00022 /************************************************************************************
00023 **  Methode:            RNSocket::RNSocket
00024 ************************************************************************************/
00025 /** Konstruktor
00026 ************************************************************************************/
00027 RNSocket::RNSocket()
00028 {
00029     m_Socket                = INVALID_SOCKET;
00030 
00031     ZeroMemory(&m_addrLocal, sizeof(m_addrLocal));
00032     ZeroMemory(&m_addrTarget, sizeof(m_addrTarget));
00033 }
00034 
00035 /************************************************************************************
00036 **  Methode:            RNSocket::~RNSocket
00037 ************************************************************************************/
00038 /** Destruktor
00039 ************************************************************************************/
00040 RNSocket::~RNSocket()
00041 {
00042     close();
00043 }
00044 
00045 /************************************************************************************
00046 **  Methode:            RNSocket::init
00047 ************************************************************************************/
00048 /** Initialisiert die Sockets mit der angegebenen Vesion. (Lädt die Windows dll)
00049 ************************************************************************************/
00050 bool RNSocket::init(int iMajorVersion /* = 1 */, int iMinorVersion /* = 1 */)
00051 {
00052     //Version erzeugen
00053     WORD wVersionReg = MAKEWORD((WORD)iMajorVersion, (WORD)iMinorVersion);
00054 
00055     if(m_bSocketInitialized)
00056     {
00057         // schon initialisiert? 
00058         return false;
00059     }
00060 
00061     if (WSAStartup(wVersionReg, &m_wsaData) != 0)
00062     {
00063         m_bSocketInitialized=false;
00064         return false;
00065     }
00066 
00067     if (    LOBYTE( m_wsaData.wVersion ) != iMajorVersion ||
00068             HIBYTE( m_wsaData.wVersion ) != iMinorVersion )
00069     {
00070         WSACleanup();
00071         m_bSocketInitialized=false;
00072         return false; 
00073     }
00074  
00075     m_bSocketInitialized=true;
00076     return true;
00077 }
00078 
00079 /************************************************************************************
00080 **  Methode:            RNSocket::cleanUp
00081 ************************************************************************************/
00082 /** Entlädt die Winsock dll mit Hilfe von WSACleanup.
00083 ************************************************************************************/
00084 bool RNSocket::cleanUp(void)
00085 {
00086     HRESULT hResult;
00087 
00088     // sind die Sockets ueberhaupt noch initialisiert ?!
00089     if(!m_bSocketInitialized)
00090     {
00091         return false;
00092     }
00093 
00094     hResult = WSACleanup();
00095 
00096     if (hResult == SOCKET_ERROR)
00097     {
00098         return false;
00099     }
00100 
00101     m_bSocketInitialized = false;
00102 
00103     // erfolgreich aufgeräumt!
00104     return true;
00105 }
00106 
00107 /************************************************************************************
00108 **  Methode:            RNSocket::create
00109 ************************************************************************************/
00110 /** Erstellt den Socket mit den entsprechenden Parametern.
00111 ************************************************************************************/
00112 bool RNSocket::create(int iAdressFamily/* =AF_INET */,
00113                       int iType/* =SOCK_STREAM */,
00114                       int iProtocol/* =IPPROTO_IP */)
00115 {
00116     if (m_Socket != INVALID_SOCKET)
00117     {
00118         close();
00119     }
00120         
00121     m_Socket = socket(  iAdressFamily,
00122                         iType,
00123                         iProtocol);
00124 
00125     if (m_Socket == INVALID_SOCKET)
00126     {
00127         return false;
00128     }
00129 
00130     //wird später für bind gebraucht
00131     m_addrLocal.sin_family=iAdressFamily;
00132 
00133     
00134     BOOL bYes=TRUE;
00135 
00136     if ( setsockopt(    m_Socket, 
00137                         SOL_SOCKET, 
00138                         SO_REUSEADDR, 
00139                         (char*)&bYes, 
00140                         sizeof(bYes)) == SOCKET_ERROR) 
00141     {
00142         return false;
00143     }
00144     
00145 
00146     return true;
00147 }
00148 
00149 /************************************************************************************
00150 **  Methode:            RNSocket::close
00151 ************************************************************************************/
00152 /** Schliesst den Socket.
00153 ************************************************************************************/
00154 bool RNSocket::close()
00155 {
00156     int iResult;
00157 
00158     iResult = closesocket(m_Socket);
00159 
00160     if(iResult == SOCKET_ERROR)
00161     {
00162         return false;
00163     }
00164 
00165     m_Socket=INVALID_SOCKET;
00166 
00167     return true;
00168 }
00169 
00170 /************************************************************************************
00171 **  Methode:            RNSocket::shutdown
00172 ************************************************************************************/
00173 /** Ruft shutdown() für den Socket mit den gewünschten Parametern auf.
00174 ************************************************************************************/
00175 bool RNSocket::shutdown(int iFlags)
00176 {
00177     int iResult;
00178 
00179     iResult = ::shutdown(m_Socket, iFlags);
00180     
00181     if(iResult == SOCKET_ERROR)
00182     {
00183         return false;
00184     }
00185 
00186     return true;
00187 }
00188 
00189 /************************************************************************************
00190 **  Methode:            RNSocket::connect
00191 ************************************************************************************/
00192 /** Öffnet eine Verbindung zur angegebenen IP-Adresse und Port.
00193 ************************************************************************************/
00194 bool RNSocket::connect(char* pcDestName, int iPort, int iAddressFamily/* =AF_INET */)
00195 {
00196     int iResult;
00197 
00198     // Ziel bestimmen
00199     m_addrTarget.sin_family     = iAddressFamily;
00200     m_addrTarget.sin_port           = htons((WORD)iPort);
00201     m_addrTarget.sin_addr.s_addr    = inet_addr(pcDestName);
00202         
00203     // und verbinden
00204     iResult = ::connect(m_Socket, 
00205                         (struct sockaddr *) &m_addrTarget,
00206                         sizeof(m_addrTarget));
00207 
00208     if (iResult == SOCKET_ERROR)
00209     {
00210         return false;
00211     }
00212 
00213     return true;
00214 }
00215 
00216 /************************************************************************************
00217 **  Methode:            RNSocket::bind
00218 ************************************************************************************/
00219 /** Bindet den Socket an den angegebenem Namen (IP) und Port.
00220 ************************************************************************************/
00221 bool RNSocket::bind(char* pcDestName, int iPort)
00222 {
00223     int iResult;
00224 
00225     // Spezification unseres Socket bestimmen
00226     if(pcDestName == NULL)
00227     {
00228         m_addrLocal.sin_addr.s_addr = htonl(INADDR_ANY);
00229     }
00230     else
00231     {
00232         m_addrLocal.sin_addr.s_addr = inet_addr(pcDestName);
00233     }
00234 
00235     m_addrLocal.sin_port = htons((WORD)iPort);
00236 
00237 
00238     iResult = ::bind(   m_Socket, 
00239                         (struct sockaddr*) &m_addrLocal, 
00240                         sizeof(m_addrLocal));
00241     
00242     if(iResult == SOCKET_ERROR)
00243     {
00244         return false;
00245     }
00246 
00247     return true;
00248 }
00249 
00250 /************************************************************************************
00251 **  Methode:            RNSocket::listen
00252 ************************************************************************************/
00253 /** Veranlasst das Lauschen an einem Socket, der vorher ge"bind"et wurde.
00254 *** iBackLog gibt an wie Connection Requests gequeued werden.
00255 ************************************************************************************/
00256 bool RNSocket::listen(int iBackLog/* =SOMAXCONN */)
00257 {
00258     int iResult;
00259 
00260     iResult = ::listen(m_Socket, iBackLog);
00261 
00262     if( iResult == SOCKET_ERROR)
00263     {
00264         return false;
00265     }
00266 
00267     return true;
00268 }
00269 
00270 /************************************************************************************
00271 **  Methode:            RNSocket::accept
00272 ************************************************************************************/
00273 /** Akzeptiert eine Verbindung, ab sofort können über den neuen Socket Daten
00274 *** ausgetauscht werden.
00275 ************************************************************************************/
00276 bool RNSocket::accept(RNSocket &socketNew)
00277 {
00278     int iAddrTargetLength = sizeof(socketNew.m_addrTarget);
00279 
00280     // anfragende Verbindung akzeptieren
00281     socketNew.m_Socket = ::accept(  m_Socket, 
00282                                     (struct sockaddr*) &socketNew.m_addrTarget, 
00283                                     &iAddrTargetLength);
00284 
00285     if(socketNew.m_Socket == INVALID_SOCKET)
00286     {
00287         return false;
00288     }
00289 
00290     return true;
00291 }
00292 
00293 /************************************************************************************
00294 **  Methode:            RNSocket::receive
00295 ************************************************************************************/
00296 /** Empfängt Daten auf dem Socket, es werden maximal piLength Daten empfangen. Sind
00297 *** es weniger, wird piLength entsprechend verändert.
00298 ************************************************************************************/
00299 bool RNSocket::receive(void* pvoidData, int* piLength, int iFlags/* =0 */)
00300 {
00301     int iDataReceived;
00302 
00303     iDataReceived=recv(m_Socket, (char*)pvoidData, *piLength, iFlags);
00304 
00305     if (iDataReceived==SOCKET_ERROR)
00306         return false;
00307 
00308     *piLength=iDataReceived;
00309 
00310     return true;
00311 }
00312 
00313 /************************************************************************************
00314 **  Methode:            RNSocket::send
00315 ************************************************************************************/
00316 /** Sendet die Daten aus dem Buffer. Es wird versucht alle Daten zu senden, und nur 
00317 *** bei einem Fehler wird abgebrochen.
00318 ************************************************************************************/
00319 bool RNSocket::send(void* pvoidData, int* piLength, int iFlags/* =0 */)
00320 {
00321     int iSendTotal = 0; // how many bytes we’ve sent
00322     int iBytesLeft = *piLength; // how many we have left to send
00323     int iBytesSend;
00324 
00325     while (iSendTotal < *piLength)
00326     {
00327         iBytesSend = ::send(m_Socket, 
00328                             ((char*)(pvoidData))+iSendTotal, 
00329                             iBytesLeft, 
00330                             iFlags);
00331         if (iBytesSend == SOCKET_ERROR )
00332         {
00333             *piLength = iSendTotal;
00334             return false;
00335         }
00336 
00337         iSendTotal += iBytesSend;
00338         iBytesLeft -= iBytesSend;
00339     }
00340 
00341     *piLength = iSendTotal;
00342 
00343     return true;
00344 }
00345 
00346 /************************************************************************************
00347 **  Methode:            RNSocket::isReadable
00348 ************************************************************************************/
00349 /** Überprüft ob der Socket "readable" ist.
00350 ***
00351 ************************************************************************************/
00352 bool RNSocket::isReadable(bool &bReadable, int iMilliSeconds)
00353 {
00354     int iResult;
00355 
00356     fd_set fdSet;
00357     
00358     FD_ZERO(&fdSet);
00359     FD_SET(m_Socket, &fdSet);
00360 
00361     timeval tvTimeOut;
00362 
00363     tvTimeOut.tv_sec=iMilliSeconds/1000;
00364     tvTimeOut.tv_usec=(iMilliSeconds%1000)*1000;
00365 
00366     iResult = ::select(0, &fdSet, NULL, NULL, &tvTimeOut);
00367 
00368     // Fehler
00369     if(iResult == SOCKET_ERROR)
00370     {
00371         // konnte status nicht ermitteln
00372         bReadable = false;
00373 
00374         return false;
00375     }
00376     
00377     // Timeout
00378     if(iResult == 0)
00379     {
00380         bReadable = false;
00381         
00382         return true;
00383     }
00384 
00385     // hat geklappt - der socket ist in lesbarem zustand
00386     bReadable = true;
00387 
00388     return true;    
00389 }
00390 
00391 /************************************************************************************
00392 **  Methode:            RNSocket::isWriteable
00393 ************************************************************************************/
00394 /** Überprüft ob der Socket "writeable" ist.
00395 ***
00396 ************************************************************************************/
00397 bool RNSocket::isWriteable(bool &bWriteable, int iMilliSeconds)
00398 {
00399     int iResult;
00400 
00401     fd_set fdSet;
00402     
00403     FD_ZERO(&fdSet);
00404     FD_SET(m_Socket, &fdSet);
00405 
00406     timeval tvTimeOut;
00407 
00408     tvTimeOut.tv_sec=iMilliSeconds/1000;
00409     tvTimeOut.tv_sec=(iMilliSeconds%1000)*1000;
00410 
00411     iResult = ::select(0, NULL, &fdSet, NULL, &tvTimeOut);
00412 
00413     // Fehler
00414     if(iResult == SOCKET_ERROR)
00415     {
00416         // konnte status nicht ermitteln        
00417         bWriteable = false;
00418 
00419         return false;
00420     }
00421     
00422     // Timeout
00423     if(iResult == 0)
00424     {
00425         bWriteable = false;
00426 
00427         return true;
00428     }
00429 
00430     // hat geklappt - der socket ist in schreibbarem zustand
00431     bWriteable = true;
00432 
00433     return true;
00434 }
00435 
00436 /************************************************************************************
00437 **  Ende der Datei:     RNSocket.cpp
00438 ************************************************************************************/

Erzeugt am Thu Apr 4 17:13:57 2002 für Rechnernetze-Aufgabe1 von doxygen1.2.13.1 geschrieben von Dimitri van Heesch, © 1997-2001