38 #include <sys/types.h>   
   41 # pragma comment (lib, "Ws2_32.lib") 
   45 # include <sys/socket.h>  
   47 # include <arpa/inet.h>   
   48 # include <netinet/in.h>  
   49 # include <netinet/tcp.h>  
   83 #define SDH_TCP_DEBUG 1 
  120     static bool    wsa_startup_called;
 
  122     if  ( !wsa_startup_called  &&  WSAStartup ( MAKEWORD ( 1, 1 ) , &wsa ) != 0 )
 
  126     wsa_startup_called = 
true;
 
  129     tcp_adr = string( _tcp_adr );
 
  130     tcp_port = _tcp_port;
 
  132     SetTimeout( _timeout );
 
  139     struct hostent *host;
 
  140     struct sockaddr_in addr;
 
  143     if  ( (addr.sin_addr.s_addr = inet_addr ( tcp_adr.c_str() )) == -1 )
 
  145     if ( !inet_aton( tcp_adr.c_str(), &addr.sin_addr ) )
 
  149         host = gethostbyname( tcp_adr.c_str() );
 
  152             throw new cTCPSerialException( 
cMsg( 
"Invalid hostname \"%s\", gethostbyname() failed: %s", tcp_adr.c_str(), GetLastErrorMessage() ) );
 
  154         addr.sin_addr = *(
struct in_addr*) host->h_addr;
 
  156     fd = socket( PF_INET, SOCK_STREAM, 0 );
 
  157     if ( fd == INVALID_SOCKET )
 
  158         throw new cTCPSerialException( 
cMsg( 
"Could not create TCP socket, socket() failed: %s", GetLastErrorMessage() ) );
 
  160     DBG( dbg << 
"Opening TCP connection to host: " << inet_ntoa( addr.sin_addr ) << 
", port: " << tcp_port << 
"\n" );
 
  162     addr.sin_port = htons( tcp_port );
 
  163     addr.sin_family = AF_INET;
 
  165     int rc = connect( fd, (
struct sockaddr*) &addr, 
sizeof(addr) );
 
  167         throw new cTCPSerialException( 
cMsg( 
"Could not connect to \"%s:%d\", connect() failed: %s", tcp_adr.c_str(), tcp_port, GetLastErrorMessage() ) );
 
  172     rc = setsockopt( fd, SOL_SOCKET, TCP_NODELAY, (
const char*) &one, 
sizeof( one ) );
 
  173 #elif defined( OSNAME_CYGWIN ) 
  175     rc = setsockopt( fd, SOL_SOCKET, TCP_NODELAY, &one, 
sizeof( one ) );
 
  182         throw new cTCPSerialException( 
cMsg( 
"Could not set option TCP_NODELAY for connection to \"%s:%d\", setsockopt failed: %s", tcp_adr.c_str(), tcp_port, GetLastErrorMessage() ) );
 
  185     SetTimeout( GetTimeout() );
 
  193     return ( fd != INVALID_SOCKET );
 
  203     DBG( dbg << 
"Closing TCP connection\n" );
 
  219         len = int( strlen( ptr ) );
 
  221     DBG( dbg << 
"cTCPSerial::write(): sending " << len << 
" bytes (hex): " << 
cHexByteString( ptr, len ) << 
"\n" );
 
  224     int bytes_sent = send( fd, ptr, len, 0 );
 
  226     if ( bytes_sent < 0  &&  errno == EAGAIN  &&  timeout_us != TIMEOUT_WAIT_FOR_EVER_US ) 
 
  229     if ( bytes_sent < 0  )
 
  230         throw new cTCPSerialException( 
cMsg( 
"Error from send to TCP \"%s:%d\": %s", tcp_adr.c_str(), tcp_port, GetLastErrorMessage() ) );
 
  231     if ( bytes_sent != len )
 
  232         throw new cTCPSerialException( 
cMsg( 
"Could only send %d/%d bytes via TCP \"%s:%d\"", bytes_sent, len, tcp_adr.c_str(), tcp_port ) );
 
  244     char* data = (
char*) _data;
 
  248     if ( _timeout_us != timeout_us )
 
  250         SetTimeout( 
double(_timeout_us) / 1E6 );
 
  255     int bytes_received = 0;
 
  256     int bytes_received_inc = 0;
 
  258         if ( _timeout_us > 0L )
 
  272             FD_ZERO( &(readfds) );
 
  273             FD_SET( fd, &(readfds) );
 
  283             struct  timeval timeout_timeval_maybe_overwritten = timeout_timeval;
 
  284             rc = select( (
int) max_socket, &readfds, 
NULL, 
NULL, &timeout_timeval_maybe_overwritten );
 
  286                 throw new cTCPSerialException( 
cMsg( 
"Error from select() for TCP connection to \"%s:%d\": %s", tcp_adr.c_str(), tcp_port, GetLastErrorMessage() ) );
 
  292             if ( !FD_ISSET( fd, &readfds ) )
 
  294                 DBG( dbg << 
"cTCPSerial::Read(): read1 " << bytes_received << 
"/" << 
size << 
" bytes (hex): " << 
cHexByteString( data, bytes_received ) << 
"\n" );
 
  295                 return bytes_received;
 
  302         bytes_received_inc = recv( fd, data+bytes_received, 
size-bytes_received, 0 );
 
  305         if ( bytes_received_inc < 0  &&  errno == EAGAIN  &&  timeout_us == TIMEOUT_RETURN_IMMEDITELY_US ) 
 
  308             DBG( dbg << 
"cTCPSerial::Read(): read2 " << bytes_received << 
"/" << 
size << 
" bytes (hex): " << 
cHexByteString( data, bytes_received ) << 
" (ignored)\n" );
 
  311         if ( bytes_received_inc < 0 )
 
  312             throw new cTCPSerialException( 
cMsg( 
"Error from recv() for TCP connection to \"%s:%d\": %s", tcp_adr.c_str(), tcp_port, GetLastErrorMessage() ) );
 
  314         bytes_received += bytes_received_inc;
 
  315     } 
while ( bytes_received < 
size && !return_on_less_data );
 
  318     if ( bytes_received < 
size && !return_on_less_data )
 
  320         DBG( dbg << 
"cTCPSerial::Read(): read3 ignoring " << bytes_received << 
"/" << 
size << 
" bytes (hex): " << 
cHexByteString( data, bytes_received ) << 
"\n" );
 
  321         throw new cTCPSerialException( 
cMsg( 
"Could only receive %d/%ld bytes via TCP \"%s:%d\"", bytes_received, 
size, tcp_adr.c_str(), tcp_port ) );
 
  325     DBG( dbg << 
"cTCPSerial::Read(): read4 " << bytes_received << 
"/" << 
size << 
" bytes (hex): " << 
cHexByteString( data, bytes_received ) << 
"\n" );
 
  326     return bytes_received;
 
  333     DBG( dbg << 
"cTCPSerial::SetTimeout(): " << _timeout << 
"\n" );
 
  335     if ( _timeout < 0.0 )
 
  337         _timeout = TIMEOUT_WAIT_FOR_EVER_S;
 
  338         timeout_us = TIMEOUT_WAIT_FOR_EVER_US;
 
  339         timeout_timeval.tv_sec  = 0;
 
  340         timeout_timeval.tv_usec = 0;
 
  345         double v3 = (_timeout - ((double)timeout_timeval.tv_sec)) * 1.0E6;
 
  346         timeout_timeval.tv_usec = (
tTimevalUSec) ( (_timeout - ((
double)timeout_timeval.tv_sec)) * 1.0E6 );
 
  348         double v = (_timeout*1.0E6);
 
  349         timeout_us = (long)v;
 
  357         u_long mode = (_timeout == 0.0);
 
  358         ioctlsocket( fd, FIONBIO, &mode );
 
  360         int flags = fcntl( fd, F_GETFL );
 
  361         if ( _timeout == 0.0 )
 
  362             fcntl( fd, F_SETFL, flags | O_NONBLOCK );
 
  364             fcntl( fd, F_SETFL, flags & ~O_NONBLOCK );