Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Changeset 7541 in orxonox.OLD for branches/network


Ignore:
Timestamp:
May 5, 2006, 3:55:47 PM (19 years ago)
Author:
rennerc
Message:

copied old networkSocket/serverSocket code in new classes

Location:
branches/network/src/lib/network
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/network/src/lib/network/tcp_server_socket.cc

    r7540 r7541  
    1414*/
    1515
     16/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
     17   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
     18*/
     19#define DEBUG_MODULE_NETWORK
     20
    1621#include "tcp_server_socket.h"
     22#include "tcp_socket.h"
    1723
     24
     25/* header for debug output */
     26#include "debug.h"
     27
     28TcpServerSocket::TcpServerSocket( int port ) : ServerSocket( port )
     29{
     30  init();
     31  listen(port);
     32}
     33
     34/**
     35 * Default destructor
     36 */
     37TcpServerSocket::~TcpServerSocket( )
     38{
     39  /* Quit SDL_net */
     40  // NOTE: what if other instances of NetworkSocket running?
     41  SDLNet_Quit();
     42  PRINTF(5)("SDL_net shutdown\n");
     43
     44  _isListening = false;
     45}
     46
     47void TcpServerSocket::init( )
     48{
     49  /* set the class id for the base object */
     50  this->setClassID(CL_SERVER_SOCKET, "TcpServerSocket");
     51
     52  terminateThread = false;
     53  listenSocket = NULL;
     54  _isListening = false;
     55
     56  if(SDLNet_Init()==-1)
     57  {
     58    PRINTF(1)("SDLNet_Init: %s\n", SDLNet_GetError());
     59    return;
     60  }
     61  else
     62    PRINTF(5)("SDL_net initialized\n");
     63
     64  PRINTF(0)("TcpServerSocket created\n");
     65}
    1866
    1967
    2068/**
    21  * constructor which listens on port
    22  * @param port port
     69 * Tells the NetworkSocket to listen on a specific port for incoming connections.
     70 * NetworkSocket::writeBytes(...) will have no effect until there is a valuable connection.
     71 * @param port
    2372 */
    24 TcpServerSocket::TcpServerSocket( int port ) : ServerSocket( port )
     73bool TcpServerSocket::listen(unsigned int port)
    2574{
     75  PRINTF(0)("TcpServerSocket::listen()\n");
     76  _isListening = true;
     77  //check if not already connected or listening
     78  if (listenSocket)
     79  {
     80    PRINTF(1)("TcpServerSocket::listen: tcpSocket!=NULL! maybe you already called listen or did not call close()!\n");
     81    _isListening = false;
     82    return false;
     83  }
     84
     85  IPaddress ip;
     86
     87  if (SDLNet_ResolveHost(&ip, NULL, port)==-1)
     88  {
     89    PRINTF(1)("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
     90    _isListening = false;
     91    return false;
     92  }
     93
     94  listenSocket = SDLNet_TCP_Open(&ip);
     95
     96  if (!listenSocket)
     97  {
     98    PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
     99    _isListening = false;
     100    return false;
     101  }
     102
     103  return true;
    26104}
    27105
    28 TcpServerSocket::~TcpServerSocket( )
     106
     107NetworkSocket* TcpServerSocket::getNewSocket( )
    29108{
    30 }
     109  if ( !listenSocket )
     110  {
     111    PRINTF(1)("listenSocket == NULL! Maybe you forgot to call listen()\n");
     112    close();
     113    return NULL;
     114  }
    31115
    32 bool TcpServerSocket::listen( unsigned int port )
    33 {
    34 }
     116  TCPsocket sock = SDLNet_TCP_Accept(listenSocket);
    35117
    36 NetworkSocket * TcpServerSocket::getNewSocket( void )
    37 {
     118  if ( !sock )
     119  {
     120    return NULL;
     121  }
     122  else
     123  {
     124    return new TcpSocket(sock);
     125  }
    38126}
    39127
    40128void TcpServerSocket::close( )
    41129{
     130  if ( listenSocket )
     131  {
     132    SDLNet_TCP_Close( listenSocket );
     133    listenSocket = NULL;
     134  }
     135
     136  _isListening = false;
    42137}
  • branches/network/src/lib/network/tcp_server_socket.h

    r7540 r7541  
    2727    virtual NetworkSocket* getNewSocket( void );
    2828    virtual void close();
     29   
     30  private:
     31    TCPsocket listenSocket;
     32    bool terminateThread;
     33
     34    bool _isListening;
     35
     36    void init();
    2937 
    3038};
  • branches/network/src/lib/network/tcp_socket.cc

    r7540 r7541  
     1
    12/*
    23   orxonox - the future of 3D-vertical-scrollers
     
    1011
    1112### File Specific:
    12    main-programmer: Christoph Renner
     13   main-programmer: Christoph Renner, David Hasenfratz
    1314   co-programmer:
    1415*/
    1516
     17
     18
     19/* this is for debug output. It just says, that all calls to PRINT() belong to the DEBUG_MODULE_NETWORK module
     20   For more information refere to https://www.orxonox.net/cgi-bin/trac.cgi/wiki/DebugOutput
     21*/
     22#define DEBUG_MODULE_NETWORK
     23
     24#include "converter.h"
     25
     26/* include your own header */
    1627#include "tcp_socket.h"
    1728
    18 /**
    19  * constructor which connects to host
     29/* header for debug output */
     30#include "debug.h"
     31
     32/**
     33 * Default constructor
     34 */
     35TcpSocket::TcpSocket()
     36{
     37  this->init();
     38}
     39
     40/**
     41 * Constructor to connect directly
    2042 */
    2143TcpSocket::TcpSocket( std::string host, int port )
    2244{
    23 }
    24 
    25 /**
    26  * default constructor
    27  */
    28 TcpSocket::TcpSocket( )
    29 {
    30 }
    31 
    32 /**
    33  * default destructor
     45  this->init();
     46  connectToServer( host, port);
     47}
     48
     49
     50TcpSocket::TcpSocket( TCPsocket sock )
     51{
     52  this->init();
     53  this->tcpSocket = sock;
     54
     55  readThread = SDL_CreateThread(thread_read, (void*)this);
     56  writeThread = SDL_CreateThread(thread_write, (void*)this);
     57}
     58
     59void TcpSocket::init()
     60{
     61  /* set the class id for the base object */
     62  this->setClassID(CL_NETWORK_SOCKET, "TcpSocket");
     63
     64  tcpSocket = NULL;
     65  incomingBufferLength = 0;
     66  outgoingBufferLength = 0;
     67
     68  readThread = NULL;
     69  writeThread = NULL;
     70
     71
     72  thread_write_running = false;
     73  thread_read_running = false;
     74
     75  incomingBufferMutex = SDL_CreateMutex();
     76  outgoingBufferMutex = SDL_CreateMutex();
     77
     78
     79  socketMutex = SDL_CreateMutex();
     80  terminateThread = false;
     81
     82  /* Init SDL_net */
     83  //NOTE: do we need to call SDLNet_Init for all instances?
     84  if(SDLNet_Init()==-1)
     85  {
     86    PRINTF(1)("SDLNet_Init: %s\n", SDLNet_GetError());
     87    return;
     88  }
     89  else
     90    PRINTF(5)("SDL_net initialized\n");
     91
     92  PRINTF(0)("TcpSocket created\n");
     93
     94}
     95
     96
     97
     98/**
     99 * Default destructor
     100 * dont use this from outside: use destroy() instead!!
    34101 */
    35102TcpSocket::~TcpSocket( )
    36103{
    37 }
    38    
    39 /**
    40  * read a packet sent by another NetworkSocket
    41  * @param data data will be copied here
    42  * @param maxLength readPacket will not read more than maxLength
    43  * @return bytes read. on error less than zero
    44  */
     104  this->terminateThread = true;
     105  /* Quit SDL_net */
     106  // NOTE: what if other instances of TcpSocket running?
     107  SDLNet_Quit();
     108  PRINTF(5)("SDL_net shutdown\n");
     109
     110  SDL_DestroyMutex(incomingBufferMutex);
     111  SDL_DestroyMutex(outgoingBufferMutex);
     112  SDL_DestroyMutex(socketMutex);
     113  SDL_DestroyMutex(threadTerminationMutex);
     114}
     115
     116/**
     117 * This function establishes a TCP/UDP connection to a given server (function argument).
     118 * It is called by the NetworkStream. It creates a TCP/UDP socket for the connection.
     119 * @param ip
     120 */
     121void TcpSocket::connectToServer( std::string host, int port)
     122{
     123  IPaddress ip;
     124 
     125  bOk = true;
     126 
     127  if ( SDLNet_ResolveHost( &ip, host.c_str(), port ) != 0 )
     128  {
     129    PRINTF(1)("could not resolve host %s\n", host.c_str() );
     130    bOk = false;
     131    return;
     132  }
     133 
     134  //check if not already connected or listening
     135  if (tcpSocket)
     136  {
     137    PRINTF(1)("TcpSocket::listen: tcpSocket!=NULL! maybe you already called listen or connectToServer or did not call disconnectServer()!");
     138  }
     139
     140  /* Connect to the host and port contained in ip using a TCP connection. */
     141  tcpSocket = SDLNet_TCP_Open(&ip);
     142  if(!tcpSocket)
     143  {
     144    PRINTF(1)("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
     145    return;
     146  }
     147
     148  readThread = SDL_CreateThread(thread_read, (void*)this);
     149  writeThread = SDL_CreateThread(thread_write, (void*)this);
     150}
     151
     152
     153/**
     154 * DTears down a TCP/UDP connection.
     155 */
     156void TcpSocket::disconnectServer( )
     157{
     158  terminateThread = true;
     159  /* Close the connection */
     160
     161  SDL_mutexP(socketMutex);
     162  SDLNet_TCP_Close(tcpSocket);
     163  tcpSocket = NULL;
     164  SDL_mutexV(socketMutex);
     165}
     166
     167
     168/**
     169 * This function writes some bytes (data) to the network connection (if the connection is already
     170 * estabilhed) otherwise it just does nothing (silently discarding the data). And writes some
     171 * warnings
     172 * @param data: pointer to the data to send
     173 * @param length: n bytes to send
     174 * @return the number successfully written bytes
     175 */
     176int TcpSocket::writeBytes(byte * data, int length)
     177{
     178  PRINTF(5)("TcpSocket::writeBytes()\n");
     179#ifdef _USE_OUTGOING_BUFFER
     180
     181#define min(a,b) (a<b)?a:b
     182  int nbytes = min(_OUTGOING_BUFFER_SIZE - outgoingBufferLength, length);
     183#undef min
     184
     185  if (!tcpSocket || data==NULL || nbytes<=0)
     186{
     187  assert(_OUTGOING_BUFFER_SIZE - outgoingBufferLength > 0);
     188  return 0;
     189}
     190
     191  SDL_mutexP(outgoingBufferMutex);
     192
     193  memcpy(outgoingBuffer + outgoingBufferLength, data, nbytes);
     194  outgoingBufferLength += nbytes;
     195
     196  SDL_mutexV(outgoingBufferMutex);
     197
     198
     199  return nbytes;
     200#else
     201  SDL_mutexP(socketMutex);
     202
     203  if (!tcpSocket || data==NULL)
     204    return 0;
     205
     206  int res = SDLNet_TCP_Send(tcpSocket, data, length);
     207
     208  SDL_mutexV(socketMutex);
     209
     210  if (res<length)
     211    PRINTF(1)("SDLNet_TCP_Send: %s\n", SDLNet_GetError());
     212
     213  return res;
     214#endif
     215}
     216
     217/**
     218 * Reads in the bytes from the network interface and passes it to the NetworkStream.
     219 * This function must internaly be implemented/connected as a thread, since the read
     220 * functions of many network libraries are blocking an would therefore block the whole
     221 * program.
     222 * From outside, the thread shouldn't be accessible at all.
     223 * @param data: pointer to memory, big enough to store length bytes
     224 * @param length: n bytes to read
     225 * @return the number successfully read bytes. -1 on error. may be less than length!
     226 */
     227int TcpSocket::readBytes(byte * data, int length)
     228{
     229  PRINTF(5)("TcpSocket::readBytes()\n");
     230  if (data==NULL)
     231    return 0;
     232
     233  int nbytes = (length<incomingBufferLength) ? length : incomingBufferLength;
     234
     235
     236  //printf("readBytes: nbytes = %d; length=%d; incomingBufferLength=%d\n", nbytes, length, incomingBufferLength);
     237
     238  // just in case ...
     239  if (nbytes<0)
     240    return -1;
     241
     242  if (nbytes==0)
     243    return 0;
     244
     245  SDL_mutexP(incomingBufferMutex);
     246
     247  memcpy(data, incomingBuffer, nbytes);
     248
     249  //important: use memmove because the memory areas may overlap
     250  memmove(incomingBuffer, incomingBuffer+nbytes, incomingBufferLength-nbytes);
     251  incomingBufferLength -= nbytes;
     252
     253  SDL_mutexV(incomingBufferMutex);
     254
     255  return nbytes;
     256}
     257
     258/**
     259 * Reads in the bytes form the network interface and passes it to the NetworkStream.
     260 * It only reads the bytes if there are enough bytes in our buffer.
     261 * @param data: pointer to memory, big enough to store length bytes
     262 * @param length: n bytes to read
     263 * @return the number successfully read bytes. -1 on error. 0 if there are not enough bytes in our buffer.
     264 */
     265int TcpSocket::readBlock(byte * data, int length)
     266{
     267  printf("TcpSocket: got %i bytes, NetworkStream requested %i bytes\n", this->incomingBufferLength, length);
     268  if (incomingBufferLength >= length)
     269    return readBytes(data, length);
     270  else return 0;
     271}
     272
     273
     274/**
     275 * used to create a thread to read from socket
     276 * @param data: pointer to TcpSocket
     277 */
     278int TcpSocket::thread_read( void * data )
     279{
     280  int nbytesread = 0;
     281  int nbytestoread = 0;
     282  char buffer[_LOCAL_BUFFER_SIZE];
     283  TcpSocket * self = (TcpSocket*)data;
     284
     285  self->thread_read_running = true;
     286
     287  while (!self->terminateThread)
     288  {
     289#define min(a,b) (a<b)?a:b
     290    nbytestoread = min(_INCOMING_BUFFER_SIZE - self->incomingBufferLength, _LOCAL_BUFFER_SIZE);
     291#undef min
     292
     293    //if buffer is full
     294    if (nbytestoread<=0 || !self->tcpSocket)
     295{
     296  SDL_Delay(_MSECONDS_SLEEP_FULL_BUFFER);
     297  continue;
     298}
     299
     300    nbytesread = SDLNet_TCP_Recv(self->tcpSocket, buffer, nbytestoread);
     301
     302    SDL_mutexP(self->incomingBufferMutex);
     303
     304    if (nbytesread<=0)
     305{
     306  if (nbytesread<0)
     307    printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
     308
     309  SDL_mutexP(self->socketMutex);
     310
     311  SDLNet_TCP_Close(self->tcpSocket);
     312  self->tcpSocket = NULL;
     313
     314  SDL_mutexV(self->socketMutex);
     315  SDL_mutexV(self->incomingBufferMutex);
     316  continue;
     317}
     318
     319    //printf("thread_read: nbytesread=%d\n", nbytesread);
     320
     321    memcpy(self->incomingBuffer+self->incomingBufferLength, buffer, nbytesread);
     322    self->incomingBufferLength += nbytesread;
     323
     324    SDL_mutexV(self->incomingBufferMutex);
     325  }
     326
     327  SDL_mutexP(self->threadTerminationMutex);
     328  self->thread_read_running = false;
     329
     330  if ( !self->thread_write_running )
     331{
     332    //delete self;
     333  SDL_mutexV(self->threadTerminationMutex);
     334}
     335  else
     336{
     337  SDL_mutexV(self->threadTerminationMutex);
     338}
     339
     340
     341#ifdef DONTEXITTHREADS
     342  while ( true )
     343{
     344  SDL_Delay(1000);
     345}
     346#endif
     347 
     348  PRINTF(0)("QUIT READ THREAD\n");
     349 
     350  return 0;
     351}
     352
     353int TcpSocket::thread_write( void * data )
     354{
     355  int nbyteswrite = 0;
     356  int nbytestowrite = 0;
     357  char buffer[_LOCAL_BUFFER_SIZE];
     358  TcpSocket * self = (TcpSocket*)data;
     359
     360  self->thread_write_running = true;
     361
     362  while (!self->terminateThread)
     363  {
     364#define min(a,b) (a<b)?a:b
     365    nbytestowrite = min(self->outgoingBufferLength, _LOCAL_BUFFER_SIZE);
     366#undef min
     367
     368//     printf("thread_write nbytes=%d listening=%d\n", nbytestowrite, (int)self->_isListening);
     369
     370    //if buffer is full
     371    if (nbytestowrite<=0 || !self->tcpSocket)
     372{
     373  SDL_Delay(_MSECONDS_SLEEP_EMPTY_BUFFER);
     374  continue;
     375}
     376
     377    SDL_mutexP(self->outgoingBufferMutex);
     378
     379    //printf("a\n");
     380
     381    memcpy(buffer, self->outgoingBuffer, nbytestowrite);
     382    self->outgoingBufferLength -= nbytestowrite;
     383    memmove(self->outgoingBuffer, self->outgoingBuffer+nbytestowrite, self->outgoingBufferLength);
     384
     385    SDL_mutexV(self->outgoingBufferMutex);
     386
     387    nbyteswrite = SDLNet_TCP_Send(self->tcpSocket, buffer, nbytestowrite);
     388
     389    if (nbyteswrite<=0)
     390{
     391  printf("SDLNet_TCP_Recv: %s\n", SDLNet_GetError());
     392
     393  SDL_mutexP(self->socketMutex);
     394
     395  SDLNet_TCP_Close(self->tcpSocket);
     396  self->tcpSocket = NULL;
     397
     398  SDL_mutexV(self->socketMutex);
     399  continue;
     400}
     401
     402  }
     403
     404  SDL_mutexP(self->threadTerminationMutex);
     405  self->thread_write_running = false;
     406
     407  if ( !self->thread_read_running )
     408{
     409    //delete self;
     410  SDL_mutexV(self->threadTerminationMutex);
     411}
     412  else
     413{
     414  SDL_mutexV(self->threadTerminationMutex);
     415}
     416
     417#ifdef DONTEXITTHREADS
     418  while ( true )
     419{
     420  SDL_Delay(1000);
     421}
     422#endif
     423
     424  PRINTF(0)("QUIT WRITE THREAD\n");
     425
     426  return 0;
     427 
     428}
     429
     430bool TcpSocket::writePacket( byte * data, int length )
     431{
     432  PRINTF(5)("TcpSocket::writePacket() size=%d\n", length);
     433
     434  if ( length > 1024 )
     435    PRINTF(2)("WARNING SENDING BIG PACKET SIZE = %d\n", length);
     436
     437  byte blen[INTSIZE];
     438
     439  Converter::intToByteArray( length, blen, INTSIZE );
     440
     441  writeBytes(blen, INTSIZE);
     442  writeBytes(data, length);
     443}
     444
    45445int TcpSocket::readPacket( byte * data, int maxLength )
    46446{
    47 }
    48 
    49 /**
    50  * send packet to connected socket. will be recieved as whole packet
    51  * @param data pointer to data to send
    52  * @param length lengt of packet to send
    53  * @return true on success
    54  */
    55 bool TcpSocket::writePacket( byte * data, int length )
    56 {
    57 }
    58 
    59 /**
    60  * disconnect from server
    61  */
    62 void TcpSocket::disconnectServer( )
    63 {
    64 }
    65 
    66 /**
    67  * connect to server on host with port port
    68  * @param host hostname might be xxx.xxx.xxx.xxx or localhost ...
    69  * @param port port to connect to
    70  */
    71 void TcpSocket::connectToServer( std::string host, int port )
    72 {
    73 }
    74 
     447  PRINTF(5)("TcpSocket::readPacket()\n");
     448  if (incomingBufferLength<INTSIZE)
     449  {
     450    return 0;
     451  }
     452
     453  int blen;
     454  Converter::byteArrayToInt( incomingBuffer, &blen );
     455
     456  if (blen>maxLength)
     457  {
     458    PRINTF(1)("Buffersize is too small (%d) for packet (%d).\n", maxLength, blen);
     459    assert(false);
     460    return 0;
     461  }
     462
     463  if (blen>incomingBufferLength)
     464  {
     465    return 0;
     466  }
     467
     468  byte t[INTSIZE];
     469  readBytes(t, INTSIZE);
     470  int res = readBytes(data, blen);
     471
     472  if (res!=blen)
     473    return -1;
     474  else
     475    return blen;
     476
     477}
     478
     479
  • branches/network/src/lib/network/tcp_socket.h

    r7540 r7541  
    88#define _TCP_SOCKET
    99
     10//TODO HACK else gdb will not work on server
     11#define DONTEXITTHREADS
     12
     13//if you want to use outgoing buffer define _USE_OUTGOING_BUFFER
     14#define _USE_OUTGOING_BUFFER
     15
     16#define _INCOMING_BUFFER_SIZE 2024000
     17#define _OUTGOING_BUFFER_SIZE 2024000
     18#define _LOCAL_BUFFER_SIZE 1024
     19//sleep if incoming buffer is full
     20#define _MSECONDS_SLEEP_FULL_BUFFER 10
     21//sleep if outgoing buffer is empty
     22#define _MSECONDS_SLEEP_EMPTY_BUFFER 10
     23
     24
     25/* contains memmove and memcpy */
     26#include <string.h>
     27
     28#ifdef HAVE_SDL_H
     29#include <SDL_thread.h>
     30#else
     31#include <SDL/SDL_thread.h>
     32#endif
    1033/* include this file, it contains some default definitions */
    1134#include "netdefs.h"
    1235
    1336
    14 /* include base_object.h since all classes are derived from this one */
     37/* include network_socket.h since all classes are derived from this one */
    1538#include "network_socket.h"
    1639
     
    2043    TcpSocket();
    2144    TcpSocket( std::string host, int port );
     45    TcpSocket(TCPsocket sock);
    2246    virtual ~TcpSocket();
    2347
     
    3054    virtual int readPacket(byte * data, int maxLength);
    3155
     56  private:
     57    TCPsocket tcpSocket;
     58
     59    byte incomingBuffer[_INCOMING_BUFFER_SIZE];
     60#ifdef _USE_OUTGOING_BUFFER
     61  byte outgoingBuffer[_OUTGOING_BUFFER_SIZE];
     62#endif
     63  int incomingBufferLength;
     64#ifdef _USE_OUTGOING_BUFFER
     65  int outgoingBufferLength;
     66#endif
     67
     68  SDL_mutex * incomingBufferMutex;
     69#ifdef _USE_OUTGOING_BUFFER
     70  SDL_mutex * outgoingBufferMutex;
     71#endif
     72  SDL_mutex * socketMutex;
     73  bool terminateThread;
     74
     75  SDL_mutex* threadTerminationMutex;
     76  static int thread_read(void * data);
     77  bool thread_read_running;
     78  bool thread_write_running;
     79
     80  SDL_Thread*            readThread;
     81  SDL_Thread*            writeThread;
     82
     83#ifdef _USE_OUTGOING_BUFFER
     84  static int thread_write(void * data);
     85#endif
     86
     87  int writeBytes(byte * data, int length);
     88  int readBytes(byte * data, int length);
     89  int readBlock(byte * data, int length);
     90
     91  void init();
    3292
    3393};
  • branches/network/src/lib/network/udp_socket.cc

    r7540 r7541  
    2020void UdpSocket::init( )
    2121{
     22  //TODO setClassId
    2223  this->serverSocket = NULL;
    2324  this->socket = NULL;
Note: See TracChangeset for help on using the changeset viewer.