Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 9246 in orxonox.OLD


Ignore:
Timestamp:
Jul 11, 2006, 7:50:12 PM (18 years ago)
Author:
patrick
Message:

some network comments

Location:
trunk/src/lib/network
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/network/netdefs.h

    r8802 r9246  
    2525
    2626
     27//!< enum indicating the type of the node
    2728typedef enum {
    2829  NET_SERVER,
     
    3031} NodeType;
    3132
     33//!< enum indicating the type of the network connection (2 protocols supported)
    3234typedef enum ConnectionType {
    3335  NET_UDP = 0,
     
    3537};
    3638
    37 
     39//!< the type of the user id (special number never used elsewhere)
    3840typedef enum {
    3941  NET_UID_UNASSIGNED = -1,
  • trunk/src/lib/network/network_stream.cc

    r9235 r9246  
    1010
    1111### File Specific:
    12    main-programmer: claudio
    13    co-programmer:
     12   main-programmer: Christoph Renner rennerc@ee.ethz.ch
     13   co-programmer:   Patrick Boenzli  boenzlip@orxonox.ethz.ch
    1414*/
    1515
    1616
    17 /* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
    18    For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
    19 */
    2017#define DEBUG_MODULE_NETWORK
    2118
     
    6461
    6562
     63/**
     64 * connect to a server as a client
     65 *  @param host: host name (address)
     66 *  @param port: port number
     67 */
    6668NetworkStream::NetworkStream( std::string host, int port )
    6769{
     
    7577
    7678
     79/**
     80 * start as a server
     81 *  @param port: at this port
     82 */
    7783NetworkStream::NetworkStream( int port )
    7884{
     
    8490
    8591
     92/**
     93 * generic init functions
     94 */
    8695void NetworkStream::init()
    8796{
     
    93102  myHostId = 0;
    94103  currentState = 0;
    95  
     104
    96105  remainingBytesToWriteToDict = Preferences::getInstance()->getInt( "compression", "writedict", 0 );
    97  
     106
    98107  assert( Zip::getInstance()->loadDictionary( "testdict" ) >= 0 );
    99108  this->dictClient = Zip::getInstance()->loadDictionary( "dict2pl_client" );
     
    104113
    105114
     115/**
     116 * deconstructor
     117 */
    106118NetworkStream::~NetworkStream()
    107119{
     
    120132      i->second.socket = NULL;
    121133    }
    122    
     134
    123135    if ( i->second.handshake )
    124136    {
     
    126138      i->second.handshake = NULL;
    127139    }
    128    
     140
    129141    if ( i->second.connectionMonitor )
    130142    {
     
    138150
    139151
     152/**
     153 * creates a new instance of the network game manager
     154 */
    140155void NetworkStream::createNetworkGameManager()
    141156{
     
    148163
    149164
     165/**
     166 * starts the network handshake
     167 */
    150168void NetworkStream::startHandshake()
    151169{
     
    154172  assert( peers[0].handshake == NULL );
    155173  peers[0].handshake = hs;
    156  
     174
    157175  hs->setPreferedNickName( Preferences::getInstance()->getString( "multiplayer", "nickname", "Player" ) );
    158  
     176
    159177//   peers[0].handshake->setSynchronized( true );
    160178  //this->connectSynchronizeable(*hs);
     
    164182
    165183
     184/**
     185 * this functions connects a synchronizeable to the networkstream, therefore synchronizeing
     186 * it all over the network and creating it on the other platforms (if and only if it is a
     187 * server
     188 */
    166189void NetworkStream::connectSynchronizeable(Synchronizeable& sync)
    167190{
     
    173196
    174197
     198/**
     199 * removes the synchronizeable from the list of synchronized entities
     200 */
    175201void NetworkStream::disconnectSynchronizeable(Synchronizeable& sync)
    176202{
     
    179205  if (disconnectSynchro != this->synchronizeables.end())
    180206    this->synchronizeables.erase(disconnectSynchro);
    181  
     207
    182208  oldSynchronizeables[sync.getUniqueID()] = SDL_GetTicks();
    183209}
    184210
    185211
     212/**
     213 * this is called to process data from the network socket to the synchronizeable and vice versa
     214 */
    186215void NetworkStream::processData()
    187216{
    188217  int tick = SDL_GetTicks();
    189  
     218
    190219  currentState++;
    191  
     220
    192221  if ( this->type == NET_SERVER )
    193222  {
    194223    if ( serverSocket )
    195224      serverSocket->update();
    196    
     225
    197226    this->updateConnectionList();
    198227  }
    199228  else
    200229  {
     230    // check if the connection is ok else terminate and remove
    201231    if ( peers[0].socket && ( !peers[0].socket->isOk() || peers[0].connectionMonitor->hasTimedOut() ) )
    202232    {
     
    210240        delete peers[0].handshake;
    211241      peers[0].handshake = NULL;
    212      
     242
    213243      if ( peers[0].connectionMonitor )
    214244        delete peers[0].connectionMonitor;
     
    219249  cleanUpOldSyncList();
    220250  handleHandshakes();
    221  
     251
    222252  // order of up/downstream is important!!!!
    223253  // don't change it
    224254  handleDownstream( tick );
    225255  handleUpstream( tick );
    226 
    227 }
    228 
     256}
     257
     258
     259/**
     260 * if we are a server update the connection list to accept new connections (clients)
     261 * also start the handsake for the new clients
     262 */
    229263void NetworkStream::updateConnectionList( )
    230264{
     
    233267  NetworkSocket* tempNetworkSocket = serverSocket->getNewSocket();
    234268
     269  // we got new network node
    235270  if ( tempNetworkSocket )
    236271  {
    237272    int clientId;
    238     if ( freeSocketSlots.size() >0 )
     273    // if there is a list of free client id slots, take these
     274    if ( freeSocketSlots.size() > 0 )
    239275    {
    240276      clientId = freeSocketSlots.back();
     
    246282      peers[clientId].userId = clientId;
    247283      peers[clientId].isServer = false;
    248     } else
     284    }
     285    else
    249286    {
    250287      clientId = 1;
    251      
     288
    252289      for ( PeerList::iterator it = peers.begin(); it != peers.end(); it++ )
    253290        if ( it->first >= clientId )
    254291          clientId = it->first + 1;
    255      
     292
    256293      peers[clientId].socket = tempNetworkSocket;
    257294      peers[clientId].handshake = new Handshake(true, clientId, this->networkGameManager->getUniqueID(), MessageManager::getInstance()->getUniqueID());
     
    260297      peers[clientId].userId = clientId;
    261298      peers[clientId].isServer = false;
    262      
     299
    263300      PRINTF(0)("num sync: %d\n", synchronizeables.size());
    264301    }
    265302
     303    // check if there are too many clients connected
    266304    if ( clientId > MAX_CONNECTIONS )
    267305    {
     
    270308    }
    271309    else
    272 
    273     PRINTF(0)("New Client: %d\n", clientId);
     310    {
     311      PRINTF(0)("New Client: %d\n", clientId);
     312    }
    274313
    275314    //this->connectSynchronizeable(*handshakes[clientId]);
    276315  }
     316
     317
    277318
    278319  //check if connections are ok else remove them
    279320  for ( PeerList::iterator it = peers.begin(); it != peers.end(); )
    280321  {
    281     if ( 
     322    if (
    282323          it->second.socket &&
    283           ( 
     324          (
    284325            !it->second.socket->isOk()  ||
    285326            it->second.connectionMonitor->hasTimedOut()
     
    291332        reason = "timeout";
    292333      PRINTF(0)("Client is gone: %d (%s)\n", it->second.userId, reason.c_str());
    293      
    294       //assert(false);
    295 
     334
     335
     336      // clean up the network data
    296337      it->second.socket->disconnectServer();
    297338      delete it->second.socket;
     
    301342        delete it->second.connectionMonitor;
    302343      it->second.connectionMonitor = NULL;
    303      
     344
    304345      if ( it->second.handshake )
    305346        delete it->second.handshake;
    306347      it->second.handshake = NULL;
    307      
     348
    308349      for ( SynchronizeableList::iterator it2 = synchronizeables.begin(); it2 != synchronizeables.end(); it2++ )
    309350      {
     
    314355
    315356      freeSocketSlots.push_back( it->second.userId );
    316      
     357
    317358      PeerList::iterator delit = it;
    318359      it++;
    319      
     360
    320361      peers.erase( delit );
    321      
     362
    322363      continue;
    323364    }
    324    
     365
    325366    it++;
    326367  }
     
    328369
    329370}
     371
    330372
    331373void NetworkStream::debug()
     
    348390
    349391
     392/**
     393 * @returns the number of synchronizeables registered to this stream
     394 */
    350395int NetworkStream::getSyncCount()
    351396{
     
    359404}
    360405
    361 /**
    362  * check if handshakes completed
     406
     407/**
     408 * check if handshakes completed. if so create the network game manager else remove it again
    363409 */
    364410void NetworkStream::handleHandshakes( )
     
    383429              MessageManager::getInstance()->setUniqueID( it->second.handshake->getMessageManagerId() );
    384430            }
    385              
     431
    386432
    387433            PRINT(0)("handshake finished id=%d\n", it->second.handshake->getNetworkGameManagerId());
     
    396442              {
    397443                handleNewClient( it->second.userId );
    398                
     444
    399445                if ( PlayerStats::getStats( it->second.userId ) && it->second.handshake->getPreferedNickName() != "" )
    400446                {
     
    402448                }
    403449              }
    404              
     450
    405451              PRINT(0)("handshake finished delete it\n");
    406452              delete it->second.handshake;
     
    420466}
    421467
     468
    422469/**
    423470 * handle upstream network traffic
     
    427474  int offset;
    428475  int n;
    429  
     476
    430477  for ( PeerList::reverse_iterator peer = peers.rbegin(); peer != peers.rend(); peer++ )
    431478  {
    432     offset = INTSIZE; //make already space for length
    433    
     479    offset = INTSIZE; // reserve enough space for the packet length
     480
     481    // continue with the next peer if this peer has no socket assigned (therefore no network)
    434482    if ( !peer->second.socket )
    435483      continue;
    436    
     484
     485    // header informations: current state
    437486    n = Converter::intToByteArray( currentState, buf + offset, UDP_PACKET_SIZE - offset );
    438487    assert( n == INTSIZE );
    439488    offset += n;
    440    
     489
     490    // header informations: last acked state
    441491    n = Converter::intToByteArray( peer->second.lastAckedState, buf + offset, UDP_PACKET_SIZE - offset );
    442492    assert( n == INTSIZE );
    443493    offset += n;
    444    
     494
     495    // header informations: last recved state
    445496    n = Converter::intToByteArray( peer->second.lastRecvedState, buf + offset, UDP_PACKET_SIZE - offset );
    446497    assert( n == INTSIZE );
    447498    offset += n;
    448    
     499
     500    // now write all synchronizeables in the packet
    449501    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
    450502    {
    451503      int oldOffset = offset;
    452504      Synchronizeable & sync = **it;
    453      
     505
     506      // do not include synchronizeables with uninit id and syncs that don't want to be synchronized
    454507      if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
    455508        continue;
    456509
    457       //if handshake not finished only sync handshake
     510      // if handshake not finished only sync handshake
    458511      if ( peer->second.handshake && sync.getLeafClassID() != CL_HANDSHAKE )
    459512        continue;
    460      
     513
     514      // if we are a server and this is not our handshake
    461515      if ( isServer() && sync.getLeafClassID() == CL_HANDSHAKE && sync.getUniqueID() != peer->second.userId )
    462516        continue;
    463      
    464       //do not sync null parent
     517
     518      /* list of synchronizeables that will never be synchronized over the network: */
     519      // do not sync null parent
    465520      if ( sync.getLeafClassID() == CL_NULL_PARENT )
    466521        continue;
    467522
    468523      assert( offset + INTSIZE <= UDP_PACKET_SIZE );
    469      
    470       //server fakes uniqueid=0 for handshake
     524
     525      // server fakes uniqueid == 0 for handshake
    471526      if ( this->isServer() && sync.getUniqueID() < MAX_CONNECTIONS - 1 )
    472527        n = Converter::intToByteArray( 0, buf + offset, UDP_PACKET_SIZE - offset );
    473528      else
    474529        n = Converter::intToByteArray( sync.getUniqueID(), buf + offset, UDP_PACKET_SIZE - offset );
     530
    475531      assert( n == INTSIZE );
    476532      offset += n;
    477      
    478       //make space for size
     533
     534      // make space for size
    479535      offset += INTSIZE;
    480536
    481537      n = sync.getStateDiff( peer->second.userId, buf + offset, UDP_PACKET_SIZE-offset, currentState, peer->second.lastAckedState, -1000 );
    482538      offset += n;
    483       //NETPRINTF(0)("GGGGGEEEEETTTTT: %s (%d) %d\n",sync.getClassName(), sync.getUniqueID(), n);
    484      
     539
    485540      assert( Converter::intToByteArray( n, buf + offset - n - INTSIZE, INTSIZE ) == INTSIZE );
    486      
    487       //check if all bytes == 0 -> remove data
    488       //TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff()
    489       bool allZero = true; 
    490       for ( int i = 0; i < n; i++ ) 
    491       { 
    492          if ( buf[i+oldOffset+2*INTSIZE] != 0 ) 
    493            allZero = false; 
    494       } 
    495 
    496       if ( allZero )
    497       {
    498         //NETPRINTF(n)("REMOVE ZERO DIFF: %s (%d)\n", sync.getClassName(), sync.getUniqueID());
    499         offset = oldOffset; 
    500       } 
    501 
    502      
    503     }
    504    
     541
     542      // check if all data bytes == 0 -> remove data and the synchronizeable from the sync process since there is no update
     543      // TODO not all synchronizeables like this maybe add Synchronizeable::canRemoveZeroDiff()
     544      bool allZero = true;
     545      for ( int i = 0; i < n; i++ )
     546      {
     547         if ( buf[i+oldOffset+2*INTSIZE] != 0 )
     548           allZero = false;
     549      }
     550      // if there is no new data in this synchronizeable reset the data offset to the last state -> dont synchronizes
     551      // data that hast not changed
     552      if ( allZero )
     553      {
     554        offset = oldOffset;
     555      }
     556    } // all synchronizeables written
     557
     558
     559
    505560    for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
    506561    {
    507562      Synchronizeable & sync = **it;
    508      
     563
    509564      if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
    510565        continue;
    511      
     566
    512567      sync.handleSentState( peer->second.userId, currentState, peer->second.lastAckedState );
    513568    }
    514    
     569
     570
    515571    assert( Converter::intToByteArray( offset, buf, INTSIZE ) == INTSIZE );
    516    
     572
     573    // now compress the data with the zip library
    517574    int compLength = 0;
    518575    if ( this->isServer() )
     
    520577    else
    521578      compLength = Zip::getInstance()->zip( buf, offset, compBuf, UDP_PACKET_SIZE, dictClient );
    522    
     579
    523580    if ( compLength <= 0 )
    524581    {
     
    526583      continue;
    527584    }
    528    
     585
    529586    assert( peer->second.socket->writePacket( compBuf, compLength ) );
    530    
     587
    531588    if ( this->remainingBytesToWriteToDict > 0 )
    532589      writeToNewDict( buf, offset, true );
    533    
     590
    534591    peer->second.connectionMonitor->processUnzippedOutgoingPacket( tick, buf, offset, currentState );
    535592    peer->second.connectionMonitor->processZippedOutgoingPacket( tick, compBuf, compLength, currentState );
    536    
    537     //NETPRINTF(n)("send packet: %d userId = %d\n", offset, peer->second.userId);
     593
    538594  }
    539595}
     
    545601{
    546602  int offset = 0;
    547  
     603
    548604  int length = 0;
    549605  int packetLength = 0;
     
    554610  int fromState = 0;
    555611  int syncDataLength = 0;
    556  
     612
    557613  for ( PeerList::iterator peer = peers.begin(); peer != peers.end(); peer++ )
    558614  {
    559    
     615
    560616    if ( !peer->second.socket )
    561617      continue;
     
    564620    {
    565621      peer->second.connectionMonitor->processZippedIncomingPacket( tick, compBuf, compLength );
    566      
    567       //PRINTF(0)("GGGGGOOOOOOOOOOTTTTTTTT: %d\n", compLength);
     622
    568623      packetLength = Zip::getInstance()->unZip( compBuf, compLength, buf, UDP_PACKET_SIZE );
    569624
     
    574629        continue;
    575630      }
    576      
     631
    577632      if ( this->remainingBytesToWriteToDict > 0 )
    578633        writeToNewDict( buf, packetLength, false );
    579    
     634
    580635      assert( Converter::byteArrayToInt( buf, &length ) == INTSIZE );
    581636      assert( Converter::byteArrayToInt( buf + INTSIZE, &state ) == INTSIZE );
     
    584639      //NETPRINTF(n)("ackedstate: %d\n", ackedState);
    585640      offset = 4*INTSIZE;
    586      
     641
    587642      peer->second.connectionMonitor->processUnzippedIncomingPacket( tick, buf, packetLength, state, ackedState );
    588643
    589644      //NETPRINTF(n)("got packet: %d, %d\n", length, packetLength);
    590    
     645
    591646    //if this is an old state drop it
    592647      if ( state <= peer->second.lastRecvedState )
    593648        continue;
    594    
     649
    595650      if ( packetLength != length )
    596651      {
     
    599654        continue;
    600655      }
    601      
     656
    602657      while ( offset + 2*INTSIZE < length )
    603658      {
     
    605660        assert( Converter::byteArrayToInt( buf + offset, &uniqueId ) == INTSIZE );
    606661        offset += INTSIZE;
    607      
     662
    608663        assert( Converter::byteArrayToInt( buf + offset, &syncDataLength ) == INTSIZE );
    609664        offset += INTSIZE;
    610        
     665
    611666        assert( syncDataLength > 0 );
    612667        assert( syncDataLength < 10000 );
    613      
     668
    614669        Synchronizeable * sync = NULL;
    615        
     670
    616671        for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
    617         { 
     672        {
    618673        //                                        client thinks his handshake has id 0!!!!!
    619674          if ( (*it)->getUniqueID() == uniqueId || ( uniqueId == 0 && (*it)->getUniqueID() == peer->second.userId ) )
     
    623678          }
    624679        }
    625        
     680
    626681        if ( sync == NULL )
    627682        {
     
    632687            continue;
    633688          }
    634          
     689
    635690          if ( !peers[peer->second.userId].isServer )
    636691          {
     
    638693            continue;
    639694          }
    640          
     695
    641696          int leafClassId;
    642697          if ( INTSIZE > length - offset )
     
    647702
    648703          Converter::byteArrayToInt( buf + offset, &leafClassId );
    649          
     704
    650705          assert( leafClassId != 0 );
    651        
     706
    652707          BaseObject * b = NULL;
    653708          /* These are some small exeptions in creation: Not all objects can/should be created via Factory */
     
    674729            sync->setUniqueID( uniqueId );
    675730            sync->setSynchronized(true);
    676  
     731
    677732            PRINTF(0)("Fabricated %s with id %d\n", sync->getClassName(), sync->getUniqueID());
    678733          }
     
    685740          }
    686741        }
    687        
    688 
    689         int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState ); 
     742
     743
     744        int n = sync->setStateDiff( peer->second.userId, buf+offset, syncDataLength, state, fromState );
    690745        offset += n;
    691746        //NETPRINTF(0)("SSSSSEEEEETTTTT: %s %d\n",sync->getClassName(), n);
    692747
    693748      }
    694      
     749
    695750      if ( offset != length )
    696751      {
     
    698753        peer->second.socket->disconnectServer();
    699754      }
    700      
    701      
     755
     756
    702757      for ( SynchronizeableList::iterator it = synchronizeables.begin(); it != synchronizeables.end(); it++ )
    703758      {
    704759        Synchronizeable & sync = **it;
    705      
     760
    706761        if ( !sync.beSynchronized() || sync.getUniqueID() < 0 )
    707762          continue;
    708      
     763
    709764        sync.handleRecvState( peer->second.userId, state, fromState );
    710765      }
    711      
     766
    712767      assert( peer->second.lastAckedState <= ackedState );
    713768      peer->second.lastAckedState = ackedState;
    714      
     769
    715770      assert( peer->second.lastRecvedState < state );
    716771      peer->second.lastRecvedState = state;
    717772
    718773    }
    719  
    720   }
    721  
     774
     775  }
     776
    722777}
    723778
     
    729784{
    730785  MessageManager::getInstance()->initUser( userId );
    731  
     786
    732787  networkGameManager->signalNewPlayer( userId );
    733788}
     
    739794{
    740795  int now = SDL_GetTicks();
    741  
     796
    742797  for ( std::map<int,int>::iterator it = oldSynchronizeables.begin(); it != oldSynchronizeables.end();  )
    743798  {
     
    762817  if ( remainingBytesToWriteToDict <= 0 )
    763818    return;
    764  
     819
    765820  if ( length > remainingBytesToWriteToDict )
    766821    length = remainingBytesToWriteToDict;
    767  
     822
    768823  std::string fileName = ResourceManager::getInstance()->getDataDir();
    769824  fileName += "/dicts/newdict";
    770  
     825
    771826  if ( upstream )
    772827    fileName += "_upstream";
    773828  else
    774829    fileName += "_downstream";
    775  
     830
    776831  FILE * f = fopen( fileName.c_str(), "a" );
    777  
     832
    778833  if ( !f )
    779834  {
     
    782837    return;
    783838  }
    784  
     839
    785840  if ( fwrite( data, 1, length, f ) != length )
    786841  {
     
    789844    return;
    790845  }
    791  
     846
    792847  fclose( f );
    793  
    794   remainingBytesToWriteToDict -= length; 
    795 }
    796 
    797 
    798 
    799 
    800 
    801 
     848
     849  remainingBytesToWriteToDict -= length;
     850}
     851
     852
     853
     854
     855
     856
  • trunk/src/lib/network/network_stream.h

    r8623 r9246  
    2222class NetworkGameManager;
    2323
     24//!< this structure contains informations about the network node
    2425class PeerInfo
    2526{
     
    2728    PeerInfo() { clear(); }
    2829    void clear() { userId = 0; isServer = false; socket = NULL; handshake = NULL; lastAckedState = 0; lastRecvedState = 0; connectionMonitor = NULL; }
     30
     31
     32  public:
    2933    int                 userId;
    3034    bool                isServer;
     
    7276
    7377    void debug();
    74    
     78
    7579    inline PeerInfo & getPeerInfo( int userId ) { return peers[userId]; }
    7680
     
    8084    void handleHandshakes();
    8185    void handleUpstream( int tick );
    82     void handleDownstream(int tick ); 
     86    void handleDownstream(int tick );
    8387    void handleNewClient( int userId );
    8488    void cleanUpOldSyncList();
    85    
     89
    8690    void writeToNewDict( byte * data, int length, bool upstream );
    8791
     
    96100
    97101    int                        myHostId;
    98    
     102
    99103    int                        currentState;                //!< current state id
    100104
     
    102106
    103107    std::map<int,int>          oldSynchronizeables;         //!< used to save recently deleted sync ids to not recreate them
    104    
     108
    105109    byte                       buf[UDP_PACKET_SIZE];        //!< used by handleUp/Downstream
    106110    byte                       compBuf[UDP_PACKET_SIZE];    //!< used by handleUp/Downstream
  • trunk/src/lib/network/udp_server_socket.h

    r8802 r9246  
    4747  public:
    4848    UdpServerSocket( int port);
    49 
    5049    virtual ~UdpServerSocket();
    5150
    5251    virtual bool listen( unsigned int port );
    53    
     52
    5453    virtual NetworkSocket* getNewSocket( void );
    55    
     54
    5655    virtual void close();
    57    
     56
    5857    virtual void update();
    59    
     58
    6059    void removeUserPackets( int userId );
    6160    void removeUser( int userId );
     
    6463    int getPacketCount( int childId );
    6564    void initUser( int childId, IPaddress ip, byte randomByte );
    66    
     65
    6766  private:
    6867    UDPsocket     socket;           //!< will be uses to send/recieve data
Note: See TracChangeset for help on using the changeset viewer.