You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.2KB

  1. /***************************************************/
  2. /*! \class TcpClient
  3. \brief STK TCP socket client class.
  4. This class provides a uniform cross-platform TCP socket client
  5. interface. Methods are provided for reading or writing data
  6. buffers to/from connections.
  7. TCP sockets are reliable and connection-oriented. A TCP socket
  8. client must be connected to a TCP server before data can be sent
  9. or received. Data delivery is guaranteed in order, without loss,
  10. error, or duplication. That said, TCP transmissions tend to be
  11. slower than those using the UDP protocol and data sent with
  12. multiple \e write() calls can be arbitrarily combined by the
  13. underlying system.
  14. The user is responsible for checking the values
  15. returned by the read/write methods. Values
  16. less than or equal to zero indicate a closed
  17. or lost connection or the occurence of an error.
  18. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  19. */
  20. /***************************************************/
  21. #include "TcpClient.h"
  22. #include <cstring>
  23. #include <sstream>
  24. namespace stk {
  25. TcpClient :: TcpClient( int port, std::string hostname )
  26. {
  27. #if defined(__OS_WINDOWS__) // windoze-only stuff
  28. WSADATA wsaData;
  29. WORD wVersionRequested = MAKEWORD(1,1);
  30. WSAStartup( wVersionRequested, &wsaData );
  31. if ( wsaData.wVersion != wVersionRequested ) {
  32. oStream_ << "TcpClient: Incompatible Windows socket library version!";
  33. handleError( StkError::PROCESS_SOCKET );
  34. }
  35. #endif
  36. // Create a socket client connection.
  37. connect( port, hostname );
  38. }
  39. TcpClient :: ~TcpClient( void )
  40. {
  41. }
  42. int TcpClient :: connect( int port, std::string hostname )
  43. {
  44. // Close any existing connections.
  45. this->close( soket_ );
  46. // Create the client-side socket
  47. soket_ = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  48. if ( soket_ < 0 ) {
  49. oStream_ << "TcpClient: Couldn't create socket client!";
  50. handleError( StkError::PROCESS_SOCKET );
  51. }
  52. int flag = 1;
  53. int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
  54. if ( result < 0 ) {
  55. oStream_ << "TcpClient: Error setting socket options!";
  56. handleError( StkError::PROCESS_SOCKET );
  57. }
  58. struct hostent *hostp;
  59. if ( ( hostp = gethostbyname( hostname.c_str() ) ) == 0 ) {
  60. oStream_ << "TcpClient: unknown host (" << hostname << ")!";
  61. handleError( StkError::PROCESS_SOCKET_IPADDR );
  62. }
  63. // Fill in the address structure
  64. struct sockaddr_in server_address;
  65. server_address.sin_family = AF_INET;
  66. memcpy( (void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length );
  67. server_address.sin_port = htons(port);
  68. // Connect to the server
  69. if ( ::connect( soket_, (struct sockaddr *)&server_address, sizeof(server_address) ) < 0 ) {
  70. oStream_ << "TcpClient: Couldn't connect to socket server!";
  71. handleError( StkError::PROCESS_SOCKET );
  72. }
  73. return soket_;
  74. }
  75. int TcpClient :: writeBuffer( const void *buffer, long bufferSize, int flags )
  76. {
  77. if ( !isValid( soket_ ) ) return -1;
  78. return send( soket_, (const char *)buffer, bufferSize, flags );
  79. }
  80. int TcpClient :: readBuffer( void *buffer, long bufferSize, int flags )
  81. {
  82. if ( !isValid( soket_ ) ) return -1;
  83. return recv( soket_, (char *)buffer, bufferSize, flags );
  84. }
  85. } // stk namespace