[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2. sockbuf Class

sockbuf class is derived from streambuf class of the iostream library. You can simultaneously read and write into a sockbuf just like you can listen and talk through a telephone. To accomplish the above goal, we maintain two independent buffers for reading and writing.

2.1 Constructors  How to construct a sockbuf object and how to open a socket?
2.2 Destructor  How to destruct a sockbuf object and how to close a socket?
2.3 Reading and Writing  How to use sockbuf as streambuf?
2.4 Establishing connections  How to bind an address and establish a connection?
2.5 Getting and Setting Socket Options  How to set and get socket options?
2.6 Time Outs While Reading and Writing  How to gracefully handle connection inactivity?


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 Constructors

sockbuf constructors sets up an endpoint for communication. A sockbuf object so created can be read from and written to in linebuffered mode. To change mode, refer to streambuf class in your IOStream library.

Note: If you are using AT&T IOStream library, then the linebuffered mode is permanently turned off. Thus, you need to explicitly flush a socket stream. You can flush a socket stream buffer in one of the following four ways:
 
    // os is a socket ostream
    os << "this is a test" << endl;
    os << "this is a test\n" << flush;
    os << "this is a test\n"; os.flush ();
    os << "this is a test\n"; os->sync ();

sockbuf objects are created as follows where

sockbuf s(sd);
sockbuf s;
Set socket descriptor of s to sd (defaults to -1). sockbuf destructor will close sd.

sockbuf s(af, ty, proto);
Set socket descriptor of s to ::socket(af, int(ty), proto);

sockbuf so(s);
Set socket descriptor of so to the socket descriptor of s.

s.open(ty, proto)
does nothing and returns simply 0, the null pointer to sockbuf.

s.is_open()
returns a non-zero number if the socket descriptor is open else return 0.

s = so;
return a reference s after assigning s with so.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Destructor

sockbuf::~sockbuf() flushes output and closes its socket if no other sockbuf is referencing it and _S_DELETE_DONT_CLOSE flag is not set. It also deletes its read and write buffers.

In what follows,

sockbuf::~sockbuf()
flushes output and closes its socket if no other sockbuf object is referencing it before deleting its read and write buffers. If the _S_DELETE_DONT_CLOSE flag is set, then the socket is not closed.

s.close()
closes the socket even if it is referenced by other sockbuf objects and _S_DELETE_DONT_CLOSE flag is set.

s.shutdown(how)
shuts down read if how is sockbuf::shut_read, shuts down write if how is sockbuf::shut_write, and shuts down both read and write if how is sockbuf::shut_readwrite.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 Reading and Writing

sockbuf class offers several ways to read and write and tailors the behavior of several virtual functions of streambuf for socket communication.

In case of error, sockbuf::error(const char*) is called.

In what follows,

s.is_open()
returns a non-zero number if the socket descriptor is open else return 0.

s.is_eof()
returns a non-zero number if the socket has seen EOF while reading else return 0.

s.write(buf, bufsz)
returns an int which must be equal to bufsz if bufsz chars in the buf are written successfully. It returns 0 if there is nothing to write or if, in case of timeouts, the socket is not ready for write 2.6 Time Outs While Reading and Writing.

s.send(buf, bufsz, msgf)
same as sockbuf::write described above but allows the user to control the transmission of messages using the message flag msgf. If msgf is sockbuf::msg_oob and the socket type of s is sockbuf::sock_stream, s sends the message in out-of-band mode. If msgf is sockbuf::msg_dontroute, s sends the outgoing packets without routing. If msgf is 0, which is the default case, sockbuf::send behaves exactly like sockbuf::write.

s.sendto(sa, buf, bufsz, msgf)
same as sockbuf::send but works on unconnected sockets. sa specifies the to address for the message.

s.sendmsg(msgh, msgf)
same as sockbuf::send but sends a struct msghdr object instead.

s.sys_write(buf, bufsz)
calls sockbuf::write and returns the result. Unlike sockbuf::write sockbuf::sys_write is declared as a virtual function.

s.read(buf, bufsz)
returns an int which is the number of chars read into the buf. In case of EOF, return EOF. Here, bufsz indicates the size of the buf. In case of timeouts, return 0 2.6 Time Outs While Reading and Writing.

s.recv(buf, bufsz, msgf)
same as sockbuf::read described above but allows the user to receive out-of-band data if msgf is sockbuf::msg_oob or to preview the data waiting to be read if msgf is sockbuf::msg_peek. If msgf is 0, which is the default case, sockbuf::recv behaves exactly like sockbuf::read.

s.recvfrom(sa, buf, bufsz, msgf)
same as sockbuf::recv but works on unconnected sockets. sa specifies the from address for the message.

s.recvmsg(msgh, msgf)
same as sockbuf::recv but reads a struct msghdr object instead.

s.sys_read(buf, bufsz)
calls sockbuf::read and returns the result. Unlike sockbuf::read sockbuf::sys_read is declared as a virtual function.

s.is_readready(wp_sec, wp_usec)
returns a non-zero int if s has data waiting to be read from the communication channel. If wp_sec >= 0, it waits for wp_sec 10^6 + wp_usec microseconds before returning 0 in case there are no data waiting to be read. If wp_sec < 0, then it waits until a datum arrives at the communication channel. wp_usec defaults to 0.
Please Note: The data waiting in sockbuf's own buffer is different from the data waiting in the communication channel.

s.is_writeready(wp_sec, wp_usec)
returns a non-zero int if data can be written onto the communication channel of s. If wp_sec >= 0, it waits for wp_sec 10^6 + wp_usec microseconds before returning 0 in case no data can be written. If wp_sec < 0, then it waits until the communication channel is ready to accept data. wp_usec defaults to 0.
Please Note: The buffer of the sockbuf class is different from the buffer of the communication channel buffer.

s.is_exceptionpending(wp_sec, wp_usec)
returns non-zero int if s has any exception events pending. If wp_sec >= 0, it waits for wp_sec 10^6 + wp_usec microseconds before returning 0 in case s does not have any exception events pending. If wp_sec < 0, then it waits until an expception event occurs. wp_usec defaults to 0.
Please Note: The exceptions that sockbuf::is_exceptionpending is looking for are different from the C++ exceptions.

s.flush_output()
flushes the output buffer and returns the number of chars flushed. In case of error, return EOF. sockbuf::flush_output is a protected member function and it is not available for general public.

s.doallocate()
allocates free store for read and write buffers of s and returns 1 if allocation is done and returns 0 if there is no need. sockbuf::doallocate is a protected virtual member function and it is not available for general public.

s.underflow()
returns the unread char in the buffer as an unsigned char if there is any. Else returns EOF if s cannot allocate space for the buffers, cannot read or peer is closed. sockbuf::underflow is a protected virtual member function and it is not available for general public.

s.overflow(c)
if c==EOF, call and return the result of flush_output(), else if c=='\n' and s is linebuffered, call flush_output() and return c unless flush_output() returns EOF, in which case return EOF. In any other case, insert char c into the buffer and return c as an unsigned char. sockbuf::overflow is a protected member virtual function and it is not available for general public.
Node: linebuffered mode does not work with AT&T IOStream library. Use explicit flushing to flush sockbuf.

s.sync()
calls flush_output() and returns the result. Useful if the user needs to flush the output without writing newline char into the write buffer.

s.xsputn(buf, bufsz)
write bufsz chars into the buffer and returns the number of chars successfully written. Output is flushed if any char in buf[0..bufsz-1] is '\n'.

s.recvtimeout(wp)
sets the recv timeout to wp seconds. If wp is -1, it is a block and if wp is 0, it is a poll.

It affects all read functions. If the socket is not read ready within wp seconds, the read call will return 0. It also affects sockbuf::underflow. sockbuf::underflow will not set the _S_EOF_SEEN flag if it is returning EOF because of timeout.

sockbuf::recvtimeout returns the old recv timeout value.

s.sendtimeout(wp)
sets the send timeout to wp seconds. If wp is -1, it is a block and if wp is 0, it is a poll.

It affects all write functions. If the socket is not write ready within wp seconds, the write call will return 0.

sockbuf::sendtimeout returns the old send timeout value.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 Establishing connections

A name must be bound to a sockbuf if processes want to refer to it and use it for communication. Names must be unique. A unix name is a 3-tuple, <protocol, local path, peer path>. An inet name is a 5-tuple, <protocol, local addr, local port, peer addr, peer port>. sockbuf::bind is used to specify the local half of the name---<local path> for unix and <local addr, local port> for inet. sockbuf::connect and sockbuf::accept are used to specify the peer half of the name---<peer path> for unix and <peer addr, peer port> for inet.

In what follows,

s.bind(sa)
binds sockAddr sa as the local half of the name for s. It returns 0 on success and returns the errno on failure.

s.connect(sa)
sockbuf::connect uses sa to provide the peer half of the name for s and to establish the connection itself. sockbuf::connect also provides the local half of the name automatically and hence, the user should not use sockbuf::bind to bind any local half of the name. It returns 0 on success and returns the errno on failure.

s.listen(nc)
makes s ready to accept connections. nc specifies the maximum number of outstanding connections that may be queued and must be at least 1 and less than or equal to sockbuf::somaxconn which is usually 5 on most systems.

sockbuf so (s.accept(sa))
sockbuf so (s.accept())
accepts connections and returns the peer address in sa. s must be a listening sockbuf. See sockbuf::listen above.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 Getting and Setting Socket Options

Socket options are used to control a socket communication. New options can be set and old value of the options can be retrived at the protocol level or at the socket level by using setopt and getopt member functions. In addition, you can also use special member functions to get and set specific options.

In what follows,

s.getopt(op, &opval, sizeof(opval), oplevel)
gets the option value of the sockbuf::option op at the option level oplevel in opval. It returns the actual size of the buffer opval used. The default value of the oplevel is sockbuf::sol_socket.

s.setopt(op, &opval, sizeof(opval), oplevel)
sets the option value of the sockbuf::option op at the option level oplevel to opval. The default value of the oplevel is sockbuf::sol_socket.

s.gettype()
gets the socket type of s. The return type is sockbuf::type.

s.clearerror()
gets and clears the error status of the socket.

s.debug(opval)
if opval is not -1, set the sockbuf::so_debug option value to opval. In any case, return the old option value of sockbuf::so_debug option. The default value of opval is -1.

s.reuseaddr(opval)
if opval is not -1, set the sockbuf::so_reuseaddr option value to opval. In any case, return the old option value of sockbuf::so_reuseaddr option. The default value of opval is -1.

s.dontroute(opval)
if opval is not -1, set the sockbuf::so_dontroute option value to opval. In any case, return the old option value of sockbuf::so_dontroute option. The default value of opval is -1.

s.oobinline(opval)
if opval is not -1, set the sockbuf::so_oobinline option value to opval. In any case, return the old option value of sockbuf::so_oobinline option. The default value of opval is -1.

s.broadcast(opval)
if opval is not -1, set the sockbuf::so_broadcast option value to opval. In any case, return the old option value of sockbuf::so_broadcast option. The default value of opval is -1.

s.keepalive(opval)
if opval is not -1, set the sockbuf::so_keepalive option value to opval. In any case, return the old option value of sockbuf::so_keepalive option. The default value of opval is -1.

s.sendbufsz(opval)
if opval is not -1, set the new send buffer size to opval. In any case, return the old buffer size of the send buffer. The default value of opval is -1.

s.recvbufsz(opval)
if opval is not -1, set the new recv buffer size to opval. In any case, return the old buffer size of the recv buffer. The default value of opval is -1.

s.linger(tim)
if tim is positive, set the linger time to tim seconds. If tim is 0, set the linger off. In any case, return the old linger time if it was set earlier. Otherwise return -1. The default value of tim is -1.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.6 Time Outs While Reading and Writing

Time outs are very useful in handling data of unknown sizes and formats while reading and writing. For example, how does one communicate with a socket that sends chunks of data of unknown size and format? If only sockbuf::read is used without time out, it will block indefinitely. In such cases, time out facility is the only answer.

The following idiom is recommended. See section 15. Pitfalls for a complete example.

 
    int old_tmo = s.recvtimeout (2) // set time out (2 seconds here)
    for (;;) { // read or write
        char buf[256];
        int rval = s.read (buf, 256);
        if (rval == 0 || rval == EOF) break;
        // process buf here
    }
    s.recvtimeout (old_tmo); // reset time out
In what follows,

s.recvtimeout(wp)
sets the recv timeout to wp seconds. If wp is -1, it is a block and if wp is 0, it is a poll.

It affects all read functions. If the socket is not read ready within wp seconds, the read call will return 0. It also affects sockbuf::underflow. sockbuf::underflow will not set the _S_EOF_SEEN flag if it is returning EOF because of timeout.

sockbuf::recvtimeout returns the old recv timeout value.

s.sendtimeout(wp)
sets the send timeout to wp seconds. If wp is -1, it is a block and if wp is 0, it is a poll.

It affects all write functions. If the socket is not write ready within wp seconds, the write call will return 0.

sockbuf::sendtimeout returns the old send timeout value.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Herbert Straub on June, 15 2005 using texi2html