tcp.hpp

    1: #ifndef TCP_HPP
    2: #define TCP_HPP
    3: /*------------------------------------------------------------------------------
    4: 
    5:   Author:    Andy Rushton
    6:   Copyright: (c) Andy Rushton, 2004
    7:   License:   BSD License, see ../docs/license.html
    8: 
    9:   A platform-independent (Unix and Windows anyway) interface to TCP
   10: 
   11:   ------------------------------------------------------------------------------*/
   12: #include "os_fixes.hpp"
   13: #include "smart_ptr.hpp"
   14: #include <string>
   15: 
   16: ////////////////////////////////////////////////////////////////////////////////
   17: // Internals
   18: 
   19: class TCP_connection_data;
   20: class TCP_server_data;
   21: class TCP_client_data;
   22: 
   23: ////////////////////////////////////////////////////////////////////////////////
   24: // Server Classes: A server creates a listening port which waits for incoming
   25: // connections. This is placed on the port number appropriate for the service
   26: // - for example, a Telnet server would typically use port 23. For a new
   27: // service you should of course use any port not allocated to a standard
   28: // service. I believe that RFC 1700 defines the standard service port numbers.
   29: // When an incoming connection is made, the server accepts it and in the
   30: // process creates a new connection on a different port. This leaves the
   31: // standard port listening for further connections. In effect, the server
   32: // farms out the handling of the connections themselves and only takes
   33: // responsibility for accepting the connection. This is reflected in the class
   34: // structure. A TCP_server performs the listening and accepting roles, but
   35: // creates a TCP_connection to handle the accepted connection.
   36: 
   37: class TCP_connection
   38: {
   39: public:
   40:   TCP_connection(void);
   41:   ~TCP_connection(void);
   42: 
   43:   TCP_connection(const TCP_connection&);
   44:   TCP_connection& operator=(const TCP_connection&);
   45: 
   46:   int error(void) const;
   47:   std::string message(void) const;
   48:   bool initialised(void) const;
   49:   unsigned long address(void) const;
   50:   unsigned short port(void) const;
   51:   bool send_ready(unsigned wait);
   52:   bool send (std::string& data);
   53:   bool receive_ready(unsigned wait);
   54:   bool receive (std::string& data);
   55:   bool close(void);
   56: 
   57: protected:
   58:   friend class TCP_connection_data;
   59:   friend class TCP_server_data;
   60:   smart_ptr<TCP_connection_data> m_data;
   61: };
   62: 
   63: class TCP_server
   64: {
   65: public:
   66:   TCP_server(void);
   67:   TCP_server(unsigned short port, unsigned short queue);
   68:   ~TCP_server(void);
   69: 
   70:   TCP_server(const TCP_server&);
   71:   TCP_server& operator=(const TCP_server&);
   72: 
   73:   bool initialise(unsigned short port, unsigned short queue);
   74:   bool initialised(void) const;
   75:   int error(void) const;
   76:   std::string message(void) const;
   77:   bool close(void);
   78: 
   79:   bool connection_ready(unsigned wait);
   80:   TCP_connection connection(void);
   81: 
   82: private:
   83:   friend class TCP_server_data;
   84:   smart_ptr<TCP_server_data> m_data;
   85: };
   86: 
   87: ////////////////////////////////////////////////////////////////////////////////
   88: // Client Class: a client is simpler in that there is no listening port - you
   89: // just create a connection and get on with it. Thus the client class does the
   90: // whole job - create the connection and handle communications to/from it.
   91: //
   92: // Blocking mode: To use the client in blocking mode, use non-zero timeout for
   93: // the initialisation method. In this mode, the connection operation must
   94: // complete before the call will return or an error is indicated if the
   95: // timeout is reached without completion. This usage was designed for
   96: // applications which either just to TCP and nothing else or which do TCP
   97: // operations in a separate thread.
   98: //
   99: // Non-blocking mode: To use the client in non-blocking mode, use a zero
  100: // timeout for the initialisation method. Instead, you can ask it if it has
  101: // connected once you've initialised it. It is not an error for it to be
  102: // initialised but not connected. This usage was designed so that you can poll
  103: // the connection periodically to implement a wait for as long as you like for
  104: // the connection to occur without blocking the thread that uses the client.
  105: //
  106: // In both modes, the send_ready/receive_ready methods can be called with any
  107: // timeout including zero.
  108: 
  109: class TCP_client
  110: {
  111: public:
  112:   TCP_client(void);
  113:   TCP_client(const std::string& address, unsigned short port, unsigned int timeout=0);
  114:   ~TCP_client(void);
  115: 
  116:   TCP_client(const TCP_client&);
  117:   TCP_client& operator=(const TCP_client&);
  118: 
  119:   int error(void) const;
  120:   std::string message(void) const;
  121:   bool initialise(const std::string& address, unsigned short port, unsigned int timeout=0);
  122:   bool initialised(void) const;
  123:   bool connected(void);
  124:   unsigned long address(void) const;
  125:   unsigned short port(void) const;
  126:   bool send_ready(unsigned wait = 0);
  127:   bool send (std::string& data);
  128:   bool receive_ready(unsigned wait = 0);
  129:   bool receive (std::string& data);
  130:   bool close(void);
  131: 
  132: private:
  133:   friend class TCP_client_data;
  134:   smart_ptr<TCP_client_data> m_data;
  135: };
  136: 
  137: ////////////////////////////////////////////////////////////////////////////////
  138: #endif