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