PageRenderTime 36ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/marsyas/Network/Socket.cpp

https://github.com/crmne/marsyas
C++ | 234 lines | 153 code | 52 blank | 29 comment | 31 complexity | 02af42e06916b8a15151056bfa13ae66 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. /***************************************************/
  2. /*! \class Socket
  3. \brief STK TCP socket client/server class.
  4. This class provides a uniform cross-platform
  5. TCP socket client or socket server interface.
  6. Methods are provided for reading or writing
  7. data buffers to/from connections. This class
  8. also provides a number of static functions for
  9. use with external socket descriptors.
  10. The user is responsible for checking the values
  11. returned by the read/write methods. Values
  12. less than or equal to zero indicate a closed
  13. or lost connection or the occurence of an error.
  14. by Perry R. Cook and Gary P. Scavone, 1995 - 2002.
  15. */
  16. /***************************************************/
  17. #include "Socket.h"
  18. #ifndef WIN32
  19. #include <sys/socket.h>
  20. #include <sys/types.h>
  21. #include <arpa/inet.h>
  22. #include <netdb.h>
  23. #include <unistd.h>
  24. #include <fcntl.h>
  25. #include <netinet/in.h>
  26. #else
  27. #include <Winsock2.h>
  28. #endif
  29. using namespace Marsyas;
  30. Socket :: Socket( int port )
  31. {
  32. soket = -1;
  33. server = true;
  34. poort = port;
  35. // Create a socket server.
  36. #if defined(MARSYAS_WIN32) // windoze-only stuff
  37. WSADATA wsaData;
  38. WORD wVersionRequested = MAKEWORD(1,1);
  39. WSAStartup(wVersionRequested, &wsaData);
  40. if (wsaData.wVersion != wVersionRequested) {
  41. sprintf( msg, "Socket: Incompatible Windows socket library version!" );
  42. }
  43. #endif
  44. // Create the server-side socket
  45. soket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  46. if (soket < 0) {
  47. sprintf(msg, "Socket: Couldn't create socket server!");
  48. }
  49. struct sockaddr_in mysocket;
  50. mysocket.sin_family=AF_INET;
  51. mysocket.sin_addr.s_addr=INADDR_ANY;
  52. mysocket.sin_port=htons( port );
  53. // Bind socket to the appropriate port and interface (INADDR_ANY)
  54. if (bind(soket, (struct sockaddr *)&mysocket, sizeof(mysocket)) < 0) {
  55. sprintf(msg, "Socket: Couldn't bind socket!");
  56. }
  57. // Listen for incoming connection(s)
  58. if ( listen(soket, 1) < 0 ) {
  59. sprintf(msg, "Socket: Couldn't start server listening!");
  60. }
  61. }
  62. Socket :: Socket(int port, const char *hostname )
  63. {
  64. soket = -1;
  65. server = false;
  66. poort = port;
  67. #if defined(MARSYAS_WIN32) // windoze-only stuff
  68. WSADATA wsaData;
  69. WORD wVersionRequested = MAKEWORD(1,1);
  70. WSAStartup(wVersionRequested, &wsaData);
  71. if (wsaData.wVersion != wVersionRequested) {
  72. sprintf( msg, "Socket: Incompatible Windows socket library version!" );
  73. }
  74. #endif
  75. // Create a socket client connection.
  76. connect( port, hostname );
  77. }
  78. Socket :: ~Socket()
  79. {
  80. #if (defined(MARSYAS_IRIX) || defined(MARSYAS_CYGWIN) || defined(MARSYAS_MACOSX))
  81. ::close( soket );
  82. #elif defined(MARSYAS_WIN32)
  83. ::closesocket( soket );
  84. WSACleanup();
  85. #endif
  86. }
  87. int Socket :: connect( int port, const char *hostname )
  88. {
  89. // This method is for client connections only!
  90. if ( server == true ) return -1;
  91. // Close an existing connection if it exists.
  92. if ( isValid( soket ) ) this->close();
  93. // Create the client-side socket
  94. soket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  95. if (soket < 0) {
  96. sprintf(msg, "Socket: Couldn't create socket client!");
  97. }
  98. struct hostent *hostp;
  99. if ( (hostp = gethostbyname(hostname)) == 0 ) {
  100. sprintf(msg, "Socket: unknown host (%s)!", hostname);
  101. }
  102. // Fill in the address structure
  103. struct sockaddr_in server_address;
  104. server_address.sin_family = AF_INET;
  105. memcpy((void *)&server_address.sin_addr, hostp->h_addr, hostp->h_length);
  106. server_address.sin_port = htons(port);
  107. // Connect to the server
  108. if ( ::connect(soket, (struct sockaddr *)&server_address,
  109. sizeof(server_address) ) < 0) {
  110. sprintf(msg, "Socket: Couldn't connect to socket server!");
  111. }
  112. return soket;
  113. }
  114. int Socket :: socket( void ) const
  115. {
  116. return soket;
  117. }
  118. int Socket :: port( void ) const
  119. {
  120. return poort;
  121. }
  122. int Socket :: accept( void )
  123. {
  124. if ( server )
  125. return ::accept( soket, NULL, NULL );
  126. else
  127. return -1;
  128. }
  129. bool Socket :: isValid( int socket )
  130. {
  131. return socket != -1;
  132. }
  133. void Socket :: setBlocking( int socket, bool enable )
  134. {
  135. if ( !isValid( socket ) ) return;
  136. #if (defined(MARSYAS_IRIX) || defined(MARSYAS_CYGWIN) || defined(MARSYAS_LINUX) || defined(MARSYAS_MACOSX))
  137. int tmp = ::fcntl(socket, F_GETFL, 0);
  138. if ( tmp >= 0 )
  139. tmp = ::fcntl( socket, F_SETFL, enable ? (tmp &~ O_NONBLOCK) : (tmp | O_NONBLOCK) );
  140. #elif defined(MARSYAS_WIN32)
  141. unsigned long non_block = !enable;
  142. ioctlsocket( socket, FIONBIO, &non_block );
  143. #endif
  144. }
  145. void Socket :: close( void )
  146. {
  147. if ( !isValid( soket ) ) return;
  148. this->close( soket );
  149. soket = -1;
  150. }
  151. void Socket :: close( int socket )
  152. {
  153. if ( !isValid( socket ) ) return;
  154. #if (defined(MARSYAS_IRIX) || defined(MARSYAS_CYGWIN) || defined(MARSYAS_MACOSX))
  155. ::close( socket );
  156. #elif defined(MARSYAS_WIN32)
  157. ::closesocket( socket );
  158. #endif
  159. }
  160. int Socket :: writeBuffer(const void *buffer, long bufferSize, int flags )
  161. {
  162. if ( !isValid( soket ) ) return -1;
  163. return send( soket, (const char *)buffer, bufferSize, flags );
  164. }
  165. int Socket :: writeBuffer(int socket, const void *buffer, long bufferSize, int flags )
  166. {
  167. if ( !isValid( socket ) ) return -1;
  168. return send( socket, (const char *)buffer, bufferSize, flags );
  169. }
  170. int Socket :: readBuffer(void *buffer, long bufferSize, int flags )
  171. {
  172. if ( !isValid( soket ) ) return -1;
  173. return recv( soket, (char *)buffer, bufferSize, flags );
  174. }
  175. int Socket :: readBuffer(int socket, void *buffer, long bufferSize, int flags )
  176. {
  177. if ( !isValid( socket ) ) return -1;
  178. return recv( socket, (char *)buffer, bufferSize, flags );
  179. }