From: g0dil Date: Wed, 31 Jan 2007 16:22:17 +0000 (+0000) Subject: Finished ClientSocketHandle documentation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=3601c83f32cad85638739f891218f1e5d9fa0896;p=senf.git Finished ClientSocketHandle documentation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@189 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/ClientSocketHandle.ct b/Socket/ClientSocketHandle.ct index 3f5112f..9379c7c 100644 --- a/Socket/ClientSocketHandle.ct +++ b/Socket/ClientSocketHandle.ct @@ -100,8 +100,14 @@ prefix_ unsigned senf::ClientSocketHandle::available() { unsigned nread = this->protocol().available(); if (nread == 0 && this->blocking()) { - this->waitReadable(); - nread = this->protocol().available(); + // We have to block explicitly here so we can return the + // number of bytes available explicitly. If no more date can + // be expected to arive (i.e. the other end has closed the + // connection), the socket will always be in the readable + // state. This is the only case when available() will return + // 0. + this->waitReadable(); + nread = this->protocol().available(); } return nread; } diff --git a/Socket/ClientSocketHandle.hh b/Socket/ClientSocketHandle.hh index 49eafe9..318c83d 100644 --- a/Socket/ClientSocketHandle.hh +++ b/Socket/ClientSocketHandle.hh @@ -43,11 +43,9 @@ namespace senf { /** \brief Generic SocketHandle with client interface - This class provides the client side policy interface of the - socket abstraction. ClientSocketHandle defines the complete - policy interface. It does not implement any functionality - itself however. All calls are forward to the following policy - classes: + This class provides the client side policy interface of the socket + abstraction. ClientSocketHandle defines the complete policy interface. It does not implement + any functionality itself however. All calls are forward to the following policy classes: @@ -63,38 +61,31 @@ namespace senf {
ClientSocketHandle member Policy member
sndbuf() BufferingPolicy::rcvbuf (\ref senf::BufferingPolicyBase)
- It is important to note, that not all members are always - accessible. Which are depends on the \c Policy template - argument. If any of the policy axis is left unspecified the - corresponding members will not be callable (you will get a - compile time error). Even if every policy axis is defined, - some members might (and will) not exist depending on the exact - policy. To find out, which members are available, you have to - check the documentation of the policy classes. You can also - find a summary of all active members in the leaf protocol - class documentation. - - \todo Move all not template-parameter dependent code into a - non-template base class - - \idea Give SocketHandle (and therefore ClientSocketHandle and - ServerSocketHandle) a \c protocol() template member and an - additional template arg \c Policies. This arg should be a - typelist of Poclicy classes which can be accessed. You use - protocol() to access a protocol class. \c - Policies can of course be underspecified or even empty. - - \idea add more flexible read/write members for a) - boost::arrays and arrays of other types b) std::vector (which - uses contiguous memory ..) c) other random-access containers - (we should use some configurable trait class to identify - containers with contiguous storage). Probably we should just - use a generic Boost.Range interface. Here we again come to the - point: make all except the most basic members be non-member - algorithms ? this would make the configuration of such - extenden members more flexible. - - \see \ref policy_group + It is important to note, that not all members are always accessible. Which are depends on + the \c Policy template argument. If any of the policy axis is left unspecified the + corresponding members will not be callable (you will get a compile time error). Even if + every policy axis is defined, some members might (and will) not exist if they are + meaningless for the protocol of the socket. This depends on the exact policy. + + To find out, which members are available, you have to check the documentation of the policy + classes. You can also find a summary of all members available in the leaf protocol class + documentation. + + \todo Move all not template-parameter dependent code into a non-template base class + + \idea Give SocketHandle (and therefore ClientSocketHandle and ServerSocketHandle) a \c + protocol() template member and an additional template arg \c Policies. This arg should be a + typelist of Poclicy classes which can be accessed. You use protocol() to + access a protocol class. \c Policies can of course be underspecified or even empty. + + \idea add more flexible read/write members for a) boost::arrays and arrays of other types b) + std::vector (which uses contiguous memory ..) c) other random-access containers (we should + use some configurable trait class to identify containers with contiguous storage). Probably + we should just use a generic Boost.Range interface. Here we again come to the point: make + all except the most basic members be non-member algorithms ? this would make the + configuration of such extenden members more flexible. + + \see \ref policy_group \n \ref protocol_group */ template @@ -105,8 +96,19 @@ namespace senf { /////////////////////////////////////////////////////////////////////////// // Types + /// Address type from the addressing policy typedef typename Policy::AddressingPolicy::Address Address; + /// 'Best' type for passing address as parameter + /** Depending on the type of \c Address, this will be either Address or Address + const &. See call_traits documentation in the Boost.Utility library\endlink. + */ typedef typename boost::call_traits
::param_type AddressParam; + /// Corresponding server socket handle with the same policy + /** This class will probably only be usable, if the \c CommunicationPolicy is \c + ConnectedCommunicationPolicy and the \c AddressingPolicy is not \c + NoAddressingPolicy. */ + */ typedef ServerSocketHandle ServerSocketHandle; /////////////////////////////////////////////////////////////////////////// @@ -134,68 +136,248 @@ namespace senf { ///\name Reading and Writing ///@{ - // read from socket (connected or unconnected) + /** \brief Read data from socket + + If the sockets \c FramingPolicy is \c DatagramFramingPolicy, every read() command will + return a single datagram. If the sockets FramingPolicy is StreamFraming, the operation will + return as much data as possible from the socket buffer. However it cannot be guaranteed, + that the socket buffer will be empty after read() returns. + + \attention If the space available for the data read is limited, the read will return no + more than that amount of data. For a datagram socket, a full datagram is still dequed + from the socket buffer, the remainder of the datagram will be lost. + + There are three variants of read which differ in how they return the read string. + + \throws senf::SystemException + + + This variant will read up to \c limit bytes from the + socket and return them as a \c std::string object. + + On a blocking socket, this member will \e always return some data (as long as the socket + has not been closed at the other end) and will block, if no data is available now. If + you do not want to block, you \e must make the socket non-blocking (using + FileHandle::blocking()). + + \param[in] limit Maximum number of bytes to read or 0 if unlimited. + \returns data read + + \implementation The read() family of members will use standard POSIX \c read calls, not + \c recv. + */ std::string read (unsigned limit=0); void read (std::string & buffer, unsigned limit=0); + ///< Read data into string buffer + /**< On a blocking socket, this member will \e always return + some data (as long as the socket has not been closed at + the other end) and will block, if no data is available + now. If you do not want to block, you \e must make the + socket non-blocking (using FileHandle::blocking()). + \param[out] buffer data read + \param[in] limit Maximum number of buytes to read or 0 + if unlimited + \see \ref read() */ unsigned read (char * buffer, unsigned size); + ///< Read data into memory area + /**< This variant will read data into the memory area at \c + buffer of size \c size. This is the most performant + version of read(). + \param[in] buffer address of buffer to store data at + \param[in] size size of memory buffer + \returns Number of bytes read + \see \ref read() */ - // read from unconnected socket returning peer address - std::pair + /** \brief Read data from unconnected socket returning address + + This member behaves like read() but should only be available, if the sockets \c + CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c AddressingPolicy is + not \c NoAddressingPolicy. The readfrom() family will in addition to the data return the + address of the sender. + + \throws senf::SystemException + + This variant will return the data read and the address as a std::pair. + + \returns \c std::pair of data read (a string) and the peers address + + \todo Add \c limit argument + + \implementation The readfrom() family of members will use \c recvfrom from the BSD + socket API. + */ + std::pair readfrom (); void readfrom (std::string & buffer, Address & from); + ///< Read data into string buffer + /**< This variant will return the result in the locations + passed in + \param[out] buffer data read + \param[out] from peer address + \see \ref readfrom() */ unsigned readfrom (char * buffer, unsigned size, Address & from); + ///< Read data into memory byffer + /**< This variant will read data into the memory area at \c + buffer of size \c size. This is the most performant + version of readfrom(). + \param[in] buffer address of buffer to store data at + \param[in] size size of bnuffer + \param[out] from peer address + \returns Number of bytes read + \see \ref readfrom() */ + - // write to connected socket + /** \brief Write data to socket + + The write() family of members will write out the data to the socket. If the sockets \c + FramingPolicy is \c DatagramFramingPolicy, every write() call will result in one + datagram. + + A single write call might depending on the circumstances write only part of the data. + + There are two variants of thie member + + \throws senf::SystemException + + + This variant will write out the string \c data. + + \param[in] data Data to write + \returns number of bytes written + \todo Make this member write the complete string if the socket is blocking + \implementation The write() family of members will use POSIX \c write calls, not \c + send. + */ unsigned write (std::string const & data); unsigned write (char const * buffer, unsigned size); + ///< Write data to socket from memory buffer + /**< \param[in] buffer address of buffer to write + \param[in] size amount of data to write + \returns Number of bytes written + \see \ref write() */ - // write to unconnected socket - unsigned writeto (AddressParam addr, std::string const & data); - unsigned writeto (AddressParam addr, char const * buffer, unsigned size); + /** \brief Write data to unconnected socket - ///@} + This member behaves like write() but should only be available, if the sockets \c + CommunicationPolicy is \c UnconnectedCommunicationPolicy and the \c AddressingPolicy is + not \c NoAddressingPolicy. The writeto() family of members takes the target address as + an additional argument. - /////////////////////////////////////////////////////////////////////////// - ///\name Addressing - ///@{ + There are two variants of this member. - void connect (AddressParam addr); - void bind (AddressParam addr); + \throw senf::SystemException - Address peer (); - void peer (Address & addr); - Address local (); - void local (Address & addr); + + This variant will send the string \c data to the peer \c addr. - ///@} + \param[in] addr Address of peer to send data to + \param[in] data data to send + \returns Number of bytes written + */ + unsigned writeto (AddressParam addr, std::string const & data); + unsigned writeto (AddressParam addr, char const * buffer, unsigned size); + ///< Write data from memory buffer to unconnected socket + /**< \param[in] addr Address o fpeer to send data to + \param[in] buffer address of buffer to write + \param[in] size amount of data to write + \returns Number of bytes written + \see \ref writeto() */ - /////////////////////////////////////////////////////////////////////////// - ///\name Buffering - ///@{ - - unsigned rcvbuf (); - void rcvbuf (unsigned size); - unsigned sndbuf (); - void sndbuf (unsigned size); - - ///@} - - static ClientSocketHandle cast_static(FileHandle handle); - static ClientSocketHandle cast_dynamic(FileHandle handle); + /////////////////////////////////////////////////////////////////////////// + ///\name Addressing + ///@{ + + /** \brief Connect to remote peer + + This member will establish a connection for addressable connection-oriented protocols + (that is, the CommunicationPolicy is ConnectedCommunicationPolicy and the + AddressingPolicy is not NoAddressingPolicy). + + \param[in] addr Address to connect to + + \throws senf::SystemException + */ + void connect (AddressParam addr); + + /** \brief Set local address + + For addressable protocols (AddressingPolicy is not NoAddressingPolicy), bind() will set + the local address of the socket. + + \parm[in] addr Local socket address to asign + + \throws senf::SystemException + */ + void bind (AddressParam addr); + + /** \brief Query remote address + + This member will return the address of the communication partner in addressable + connection-oriented protocols (that is, the CommunicationPolicy is + ConnectedCommunicationPolicy and the AddressingPolicy is not NoAddressingPolicy). + + There are two Variants of this member, one will return the address by value, the other + takes a reference argument to elide the copy operation. + + \throws senf::SystemException + */ + Address peer (); + void peer (Address & addr); + ///< Query remote address + /**< \see \ref peer() */ + + /** \brief Query local address + + This member will return the address of the local socket in addressable protocols + (AddressingPolicy is not NoAddressingPolicy). + + There are two Variants of this member, one will return the address by value, the other + takes a reference argument to elide the copy operation. + + */ + Address local (); + void local (Address & addr); + ///< Query local address + /**< \see \ref local() */ + + ///@} + + /////////////////////////////////////////////////////////////////////////// + ///\name Buffering + ///@{ + + unsigned rcvbuf (); ///< Check size of receive buffer + /**< \returns size of receive buffer in bytes */ + void rcvbuf (unsigned size); + ///< Set size of receive buffer + /**< \param[in] size size of receive buffer in bytes */ + + unsigned sndbuf (); ///< Check size of send buffer + /**< \returns size of send buffer in bytes */ + void sndbuf (unsigned size); + ///< Set size of send buffer + /**< \param[in] size size of send buffer in bytes */ + + ///@} + + static ClientSocketHandle cast_static(FileHandle handle); + /**< \internal */ + static ClientSocketHandle cast_dynamic(FileHandle handle); + /**< \internal */ - // we need to override both since SocketHandle is *not* polymorphic - void state(SocketStateMap & map, unsigned lod=0); - std::string dumpState(unsigned lod=0); + // we need to override both since SocketHandle is *not* polymorphic + void state(SocketStateMap & map, unsigned lod=0); + std::string dumpState(unsigned lod=0); protected: - ClientSocketHandle(FileHandle other, bool isChecked); - explicit ClientSocketHandle(std::auto_ptr protocol, - int fd = -1); + ClientSocketHandle(FileHandle other, bool isChecked); + explicit ClientSocketHandle(std::auto_ptr protocol, + int fd = -1); private: - unsigned available(); + unsigned available(); - friend class senf::ServerSocketHandle; + friend class senf::ServerSocketHandle; }; /// @} @@ -211,4 +393,5 @@ namespace senf { // Local Variables: // mode: c++ // c-file-style: "senf" +// fill-column: 100 // End: diff --git a/Socket/SocketPolicy.hh b/Socket/SocketPolicy.hh index c7ed63a..708f18a 100644 --- a/Socket/SocketPolicy.hh +++ b/Socket/SocketPolicy.hh @@ -24,12 +24,20 @@ \brief Policy Framework public header \todo We should probably remove BufferingPolicy from the - interface, it does not make much sense (how did I come to include - it ??) + interface, it does not make much sense (how did I come to + include it ??) \todo Do we want to support separate read and write policies. This - allows to treat pipes within this framework however, is this worth - the effort? + allows to treat pipes within this framework however, is this + worth the effort? + + \idea Creating a new Socket will create three new instances (The + handle, the body and the policy) of which two (body and + policy) live on the heap. This is expensive. We should check, + wether we can make all the policy classes to singletons and + assign the same instance to all socket bodies with the same + policy. This would reduce the number of allocations per socket + handle to one. */ /** \defgroup policy_group The Policy Framework