Definition
An instance sb of class socket_streambuf can be used as an adapter: It turns a
leda_socket s into a C++-streambuf object. This object can be used in
standard C++ ostreams and istreams to make the communication through
the socket easier.
A socket_streambuf can also be applied within an encoding_ostream or a
decoding_istream provided by LEDA to send compressed or encrypted data
over a socket connection (see Sections encoding_ostream and
decoding_istream).
Observe that socket_streambuf itself does not apply cryptography to secure the
transmitted data. All data is sent as it is. If you want to secure your data,
consider using the class secure_socket_streambuf
(see Section secure_socket_streambuf).
If two parties want to use the class socket_streambuf to exchange data they have to do the following. First they establish a connection through leda_sockets. Then each party contructs an instance of the class socket_streambuf which is attached to its socket. This is shown in an example at the end of this manual page.
Every instance sb has an out-buffer where outgoing data is buffered before it is sent through the socket over the internet. In addition it has an in-buffer to store data that has been received through the socket. The user may specify the maximum size of each buffer. The actual size of each buffer is determined in a negotiation between the server and the client at the beginning of the communication. The size of outgoing packets from the server is set to the minimum of the out-buffer size of the server and the in-buffer size of the client. The size of the incoming packets is determined in an analogous way.
#include < LEDA/coding/socket_streambuf.h >
Creation
socket_streambuf | sb(leda_socket& s, uint32 out_buf_sz = DefaultBufferSize, uint32 in_buf_sz = DefaultBufferSize, bool send_acknowledge = false) | |
creates a sb and attaches it to the socket s.
The parameters out_buf_sz and in_buf_sz determine the maximum size of
the out-buffer and the in-buffer. send_acknowledge specifies whether an
acknowledgement is sent for every received packet.
Precondition The connection between the server and the client must have been established when sb is created. |
Operations
The class socket_streambuf inherits most of its operations from the class streambuf that belongs to the C++ standard library. Usually there is no need to call these operations explicitly. (You can find documentation for streambuf at http://www.cplusplus.com)
bool | sb.failed() | returns whether a failure has occured. |
string | sb.get_error() | returns an error message (if available). |
void | sb.sputEOF() | signals the end of the transmission to the receiving socket, so that it does not wait for further data. (This function is called automatically in the destructor unless it has been called explicitly by the user. If sb is not immediately destroyed after the end of the transmission then you should call sputEOF explicitly, otherwise the receiving party might incur a timeout error.) |
bool | sb.has_put_EOF() | returns whether EOF has already been sent. |
bool | sb.has_got_EOF() | returns whether EOF has already been received. |
leda_socket& | sb.get_socket() | returns the socket to which sb is attached. |
uint32 | sb.get_outgoing_packet_size() | |
returns the (actual) outgoing packet size. | ||
uint32 | sb.get_incoming_packet_size() | |
returns the (actual) incoming packet size. | ||
bool | sb.waits_for_acknowledge() | |
returns whether sb expects an acknowledgement for outgoing packets. | ||
bool | sb.sends_acknowledge() | returns whether sb sends an acknowledgement for incoming packets. |
Example
The following example shows how the usage of sb from the server and from
the client side. In our example the server sends a string, which is received
by the client. (Note that it would also be possible that the client sends and
the server receives data.)
In order to add compression to the example simply replace ``ostream'' by
``encoding_ostream<Coder>'' and ``istream'' by ``decoding_istream''
as indicated in the comments.
void socket_example_server(int port) { leda_socket sock; sock.set_port(port); // open port if (! sock.listen()) { cerr << sock.get_error() << endl; return; } for (;;) { // establish connection if (! sock.accept()) { cerr << sock.get_error() << endl; continue; } // send data { socket_streambuf sb(sock); ostream out(&sb); // or: encoding_ostream<PPMIICoder> out(&sb); out << "Hello world!" << endl; } // destroys sb and calls sb.sputEOF() automatically } } void socket_example_client(int port, string host) { leda_socket sock; sock.set_host(host); sock.set_port(port); // establish connection if (! sock.connect()) { cerr << sock.get_error() << endl; return; } // receive data socket_streambuf sb(sock); istream in(&sb); // or: decoding_istream<PPMIICoder> in(&sb); string str; str.read_line(in); cout << "received: " << str << endl; }