+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <cerrno>
+#include <sys/socket.h>
+#endif
+#include <msp/core/systemerror.h>
+#include "clientsocket.h"
+#include "socket_private.h"
+
+namespace Msp {
+namespace Net {
+
+ClientSocket::ClientSocket(Family af, int type, int proto):
+ Socket(af, type, proto),
+ connecting(false),
+ connected(false),
+ peer_addr(0)
+{ }
+
+ClientSocket::ClientSocket(const Private &p, const SockAddr &paddr):
+ Socket(p),
+ connecting(false),
+ connected(true),
+ peer_addr(paddr.copy())
+{ }
+
+ClientSocket::~ClientSocket()
+{
+ signal_flush_required.emit();
+
+ delete peer_addr;
+}
+
+const SockAddr &ClientSocket::get_peer_address() const
+{
+ if(peer_addr==0)
+ throw bad_socket_state("not connected");
+ return *peer_addr;
+}
+
+unsigned ClientSocket::do_write(const char *buf, unsigned size)
+{
+ if(!connected)
+ throw bad_socket_state("not connected");
+
+ if(size==0)
+ return 0;
+
+ int ret = ::send(priv->handle, buf, size, 0);
+ if(ret<0)
+ {
+ if(errno==EAGAIN)
+ return 0;
+ else
+ throw system_error("send");
+ }
+
+ return ret;
+}
+
+unsigned ClientSocket::do_read(char *buf, unsigned size)
+{
+ if(!connected)
+ throw bad_socket_state("not connected");
+
+ if(size==0)
+ return 0;
+
+ int ret = ::recv(priv->handle, buf, size, 0);
+ if(ret<0)
+ {
+ if(errno==EAGAIN)
+ return 0;
+ else
+ throw system_error("recv");
+ }
+ else if(ret==0 && !eof_flag)
+ {
+ eof_flag = true;
+ signal_end_of_file.emit();
+ set_events(IO::P_NONE);
+ }
+
+ return ret;
+}
+
+} // namespace Net
+} // namespace Msp