/***************************************************/ /*! \class UdpSocket \brief STK UDP socket server/client class. This class provides a uniform cross-platform UDP socket server/client interface. Methods are provided for reading or writing data buffers. The constructor creates a UDP socket and binds it to the specified port. Note that only one socket can be bound to a given port on the same machine. UDP sockets provide unreliable, connection-less service. Messages can be lost, duplicated, or received out of order. That said, data transmission tends to be faster than with TCP connections and datagrams are not potentially combined by the underlying system. The user is responsible for checking the values returned by the read/write methods. Values less than or equal to zero indicate the occurence of an error. by Perry R. Cook and Gary P. Scavone, 1995--2017. */ /***************************************************/ #include "UdpSocket.h" #include #include namespace stk { UdpSocket :: UdpSocket(int port ) { validAddress_ = false; #if defined(__OS_WINDOWS__) // windoze-only stuff WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1,1); WSAStartup(wVersionRequested, &wsaData); if (wsaData.wVersion != wVersionRequested) { oStream_ << "UdpSocket: Incompatible Windows socket library version!"; handleError( StkError::PROCESS_SOCKET ); } #endif // Create the UDP socket soket_ = ::socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if ( soket_ < 0 ) { oStream_ << "UdpSocket: Couldn't create UDP socket!"; handleError( StkError::PROCESS_SOCKET ); } struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons( port ); // Bind socket to the appropriate port and interface (INADDR_ANY) if ( bind(soket_, (struct sockaddr *)&address, sizeof(address)) < 0 ) { oStream_ << "UdpSocket: Couldn't bind socket in constructor!"; handleError( StkError::PROCESS_SOCKET ); } port_ = port; } UdpSocket :: ~UdpSocket() { } void UdpSocket :: setDestination( int port, std::string hostname ) { this->setAddress( &address_, port, hostname ); validAddress_ = true; } void UdpSocket :: setAddress( struct sockaddr_in *address, int port, std::string hostname ) { struct hostent *hostp; if ( (hostp = gethostbyname( hostname.c_str() )) == 0 ) { oStream_ << "UdpSocket::setAddress: unknown host (" << hostname << ")!"; handleError( StkError::PROCESS_SOCKET_IPADDR ); } // Fill in the address structure address->sin_family = AF_INET; memcpy((void *)&address->sin_addr, hostp->h_addr, hostp->h_length); address->sin_port = htons( port ); } int UdpSocket :: writeBuffer( const void *buffer, long bufferSize, int flags ) { if ( !isValid( soket_ ) || !validAddress_ ) return -1; return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address_, sizeof(address_) ); } int UdpSocket :: readBuffer( void *buffer, long bufferSize, int flags ) { if ( !isValid( soket_ ) ) return -1; return recvfrom( soket_, (char *)buffer, bufferSize, flags, NULL, NULL ); } int UdpSocket :: writeBufferTo( const void *buffer, long bufferSize, int port, std::string hostname, int flags ) { if ( !isValid( soket_ ) ) return -1; struct sockaddr_in address; this->setAddress( &address, port, hostname ); return sendto( soket_, (const char *)buffer, bufferSize, flags, (struct sockaddr *)&address, sizeof(address) ); } } // stk namespace