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.

100 lines
2.9KB

  1. /***************************************************/
  2. /*! \class TcpServer
  3. \brief STK TCP socket server class.
  4. This class provides a uniform cross-platform TCP socket server
  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. server must accept a connection from a TCP client before data can
  9. be sent or received. Data delivery is guaranteed in order,
  10. without loss, error, or duplication. That said, TCP transmissions
  11. tend to be slower than those using the UDP protocol and data sent
  12. with 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 "TcpServer.h"
  22. namespace stk {
  23. TcpServer :: TcpServer( int port )
  24. {
  25. // Create a socket server.
  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_ << "TcpServer: Incompatible Windows socket library version!";
  32. handleError( StkError::PROCESS_SOCKET );
  33. }
  34. #endif
  35. // Create the server-side socket
  36. soket_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  37. if (soket_ < 0) {
  38. oStream_ << "TcpServer: Couldn't create socket server!";
  39. handleError( StkError::PROCESS_SOCKET );
  40. }
  41. int flag = 1;
  42. int result = setsockopt( soket_, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int) );
  43. if (result < 0) {
  44. oStream_ << "TcpServer: Error setting socket options!";
  45. handleError( StkError::PROCESS_SOCKET );
  46. }
  47. struct sockaddr_in address;
  48. address.sin_family = AF_INET;
  49. address.sin_addr.s_addr = INADDR_ANY;
  50. address.sin_port = htons( port );
  51. // Bind socket to the appropriate port and interface (INADDR_ANY)
  52. if ( bind( soket_, (struct sockaddr *)&address, sizeof(address) ) < 0 ) {
  53. oStream_ << "TcpServer: Couldn't bind socket!";
  54. handleError( StkError::PROCESS_SOCKET );
  55. }
  56. // Listen for incoming connection(s)
  57. if ( listen( soket_, 1 ) < 0 ) {
  58. oStream_ << "TcpServer: Couldn't start server listening!";
  59. handleError( StkError::PROCESS_SOCKET );
  60. }
  61. port_ = port;
  62. }
  63. TcpServer :: ~TcpServer()
  64. {
  65. }
  66. int TcpServer :: accept( void )
  67. {
  68. return ::accept( soket_, NULL, NULL );
  69. }
  70. int TcpServer :: writeBuffer(const void *buffer, long bufferSize, int flags )
  71. {
  72. if ( !isValid( soket_ ) ) return -1;
  73. return send( soket_, (const char *)buffer, bufferSize, flags );
  74. }
  75. int TcpServer :: readBuffer(void *buffer, long bufferSize, int flags )
  76. {
  77. if ( !isValid( soket_ ) ) return -1;
  78. return recv( soket_, (char *)buffer, bufferSize, flags );
  79. }
  80. } // stk namespace