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.

111 lines
3.5KB

  1. /***************************************************/
  2. /*! \class UdpSocket
  3. \brief STK UDP socket server/client class.
  4. This class provides a uniform cross-platform UDP socket
  5. server/client interface. Methods are provided for reading or
  6. writing data buffers. The constructor creates a UDP socket and
  7. binds it to the specified port. Note that only one socket can be
  8. bound to a given port on the same machine.
  9. UDP sockets provide unreliable, connection-less service. Messages
  10. can be lost, duplicated, or received out of order. That said,
  11. data transmission tends to be faster than with TCP connections and
  12. datagrams are not potentially combined by the underlying system.
  13. The user is responsible for checking the values returned by the
  14. read/write methods. Values less than or equal to zero indicate
  15. the occurence of an error.
  16. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  17. */
  18. /***************************************************/
  19. #include "UdpSocket.h"
  20. #include <cstring>
  21. #include <sstream>
  22. namespace stk {
  23. UdpSocket :: UdpSocket(int port )
  24. {
  25. validAddress_ = false;
  26. #if defined(__OS_WINDOWS__) // windoze-only stuff
  27. WSADATA wsaData;
  28. WORD wVersionRequested = MAKEWORD(1,1);
  29. WSAStartup(wVersionRequested, &wsaData);
  30. if (wsaData.wVersion != wVersionRequested) {
  31. oStream_ << "UdpSocket: Incompatible Windows socket library version!";
  32. handleError( StkError::PROCESS_SOCKET );
  33. }
  34. #endif
  35. // Create the UDP socket
  36. soket_ = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
  37. if ( soket_ < 0 ) {
  38. oStream_ << "UdpSocket: Couldn't create UDP socket!";
  39. handleError( StkError::PROCESS_SOCKET );
  40. }
  41. struct sockaddr_in address;
  42. address.sin_family = AF_INET;
  43. address.sin_addr.s_addr = INADDR_ANY;
  44. address.sin_port = htons( port );
  45. // Bind socket to the appropriate port and interface (INADDR_ANY)
  46. if ( bind(soket_, (struct sockaddr *)&address, sizeof(address)) < 0 ) {
  47. oStream_ << "UdpSocket: Couldn't bind socket in constructor!";
  48. handleError( StkError::PROCESS_SOCKET );
  49. }
  50. port_ = port;
  51. }
  52. UdpSocket :: ~UdpSocket()
  53. {
  54. }
  55. void UdpSocket :: setDestination( int port, std::string hostname )
  56. {
  57. this->setAddress( &address_, port, hostname );
  58. validAddress_ = true;
  59. }
  60. void UdpSocket :: setAddress( struct sockaddr_in *address, int port, std::string hostname )
  61. {
  62. struct hostent *hostp;
  63. if ( (hostp = gethostbyname( hostname.c_str() )) == 0 ) {
  64. oStream_ << "UdpSocket::setAddress: unknown host (" << hostname << ")!";
  65. handleError( StkError::PROCESS_SOCKET_IPADDR );
  66. }
  67. // Fill in the address structure
  68. address->sin_family = AF_INET;
  69. memcpy((void *)&address->sin_addr, hostp->h_addr, hostp->h_length);
  70. address->sin_port = htons( port );
  71. }
  72. int UdpSocket :: writeBuffer( const void *buffer, long bufferSize, int flags )
  73. {
  74. if ( !isValid( soket_ ) || !validAddress_ ) return -1;
  75. return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address_, sizeof(address_) );
  76. }
  77. int UdpSocket :: readBuffer( void *buffer, long bufferSize, int flags )
  78. {
  79. if ( !isValid( soket_ ) ) return -1;
  80. return recvfrom( soket_, (char *)buffer, bufferSize, flags, NULL, NULL );
  81. }
  82. int UdpSocket :: writeBufferTo( const void *buffer, long bufferSize, int port, std::string hostname, int flags )
  83. {
  84. if ( !isValid( soket_ ) ) return -1;
  85. struct sockaddr_in address;
  86. this->setAddress( &address, port, hostname );
  87. return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address, sizeof(address) );
  88. }
  89. } // stk namespace