Index: src/hu/varadiistvan/scpl/io/_win32/Makefile.am
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/Makefile.am	(revision 28)
+++ src/hu/varadiistvan/scpl/io/_win32/Makefile.am	(revision 30)
@@ -13,7 +13,13 @@
         ReadingBuffer.cc        \
         WritingBuffer.cc        \
+	WSAInterface.cc		\
         LocalConnector.cc       \
         LocalAcceptor.cc        \
-        LocalServerSocketBase.cc
+        LocalServerSocketBase.cc \
+	SocketEventFactory.cc	\
+	TCPConnector.cc		\
+	TCPAcceptor.cc		\
+	TCPClientSocket.cc	\
+	TCPServerSocket.cc
 
 include_vscpl_io_win32dir=$(includedir)/hu/varadiistvan/scpl/io/_win32
@@ -31,4 +37,7 @@
         WritingBuffer.h         \
         Completer.h             \
+	WSAInterface.h		\
+	SocketEventFactory.h	\
+	SocketMixin.h		\
         LocalSocket.h           \
         LocalConnector.h        \
@@ -36,3 +45,9 @@
         LocalAcceptor.h         \
         LocalServerSocketBase.h \
-        LocalServerSocket.h
+        LocalServerSocket.h     \
+	TCPSocket.h		\
+	TCPConnector.h		\
+	TCPClientSocket.h	\
+	TCPAcceptor.h		\
+	TCPServerSocketBase.h   \
+	TCPServerSocket.h
Index: src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.cc	(revision 30)
@@ -0,0 +1,74 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include <winsock2.h>
+
+#include "SocketEventFactory.h"
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::SocketEventFactory;
+
+//------------------------------------------------------------------------------
+
+HANDLE SocketEventFactory::createEvent()
+{
+    return WSACreateEvent();
+}
+
+//------------------------------------------------------------------------------
+
+bool SocketEventFactory::setEvent(HANDLE handle)
+{
+    return WSASetEvent(handle);
+}
+
+//------------------------------------------------------------------------------
+
+bool SocketEventFactory::resetEvent(HANDLE handle)
+{
+    return WSAResetEvent(handle);
+}
+
+//------------------------------------------------------------------------------
+
+void SocketEventFactory::destroyEvent(HANDLE handle)
+{
+    WSACloseEvent(handle);
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/SocketEventFactory.h	(revision 30)
@@ -0,0 +1,79 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "EventFactory.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * Event factory for socket events.
+ */
+class SocketEventFactory : public EventFactory
+{
+public:
+    /**
+     * Create an event for this object by calling WSACreateEvent and then
+     * WSAEventSelect with the given network events.
+     */
+    HANDLE createEvent() override;
+
+    /**
+     * Set the event represented by the given handle by calling WSASetEvent().
+     */
+    bool setEvent(HANDLE handle) override;
+
+    /**
+     * Reset the event represented by the given handle by calling WSAResetEvent().
+     */
+    bool resetEvent(HANDLE handle) override;
+
+    /**
+     * Destroy the event represented by the given handle by calling WSACloseEvent().
+     */
+    void destroyEvent(HANDLE handle) override;
+};
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/SocketMixin.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/SocketMixin.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/SocketMixin.h	(revision 30)
@@ -0,0 +1,99 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "Event.h"
+
+#include "WSAInterface.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * A mixin for sockets with some commong functons
+ */
+template <class Super>
+class SocketMixin : public Super
+{
+public:
+    using Super::Super;
+
+    /**
+     * Set the socket to non-blocking mode for the given events,
+     * if it has a waiter
+     */
+    bool setNonBlocking(Event& event, long eventMask);
+
+    /**
+     * Add the given event to our waiter, if any.
+     */
+    void addToWaiter(Event& event);
+};
+
+//------------------------------------------------------------------------------
+// Template definitions
+//------------------------------------------------------------------------------
+
+template <class Super>
+inline bool SocketMixin<Super>::setNonBlocking(Event& event, long eventMask)
+{
+    if (Super::waiter!=nullptr) {
+        return WSAInterface::get().eventSelect(Super::handle,
+                                               event.getHandle(), eventMask)==0;
+    } else {
+        return true;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+template <class Super>
+inline void SocketMixin<Super>::addToWaiter(Event& event)
+{
+    if (Super::waiter!=nullptr) {
+        event.addTo(*Super::waiter);
+    }
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.cc	(revision 30)
@@ -0,0 +1,89 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "TCPAcceptor.h"
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::TCPAcceptor;
+using hu::varadiistvan::scpl::io::BufferedStream;
+
+//------------------------------------------------------------------------------
+
+bool TCPAcceptor::accept()
+{
+    if (failed()) return false;
+    if (acceptedSocket!=WSAInterface::get().getInvalidSocket()) return true;
+
+    bool result = false;
+    if (checkWaitedResult(result)) {
+        return result;
+    }
+
+    handleWaitedResult(0);
+
+    return acceptedSocket!=WSAInterface::get().getInvalidSocket();
+}
+
+//------------------------------------------------------------------------------
+
+BufferedStream* TCPAcceptor::getAcceptedBufferedStream(Waiter* waiter)
+{
+    return (waiter==nullptr) ? getSocket() : getSocket(waiter);
+}
+
+//------------------------------------------------------------------------------
+
+void TCPAcceptor::handleWaitedResult(DWORD /*size*/)
+{
+    auto& socket = getServerSocket();
+    if (overlapped!=0) {
+        overlapped->reset();
+        socket.setNonBlocking(*overlapped, FD_ACCEPT);
+    }
+    acceptedSocket = socket.accept();
+    if (WSAInterface::get().isInvalidSocket(acceptedSocket) &&
+        !socket.failed())
+    {
+        if (overlapped!=0) {
+            socket.addToWaiter(*overlapped);
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPAcceptor.h	(revision 30)
@@ -0,0 +1,174 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "../BufferedStreamAcceptor.h"
+
+#include "Completer.h"
+
+#include "TCPServerSocketBase.h"
+#include "TCPSocket.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+class TCPServerSocket;
+
+//------------------------------------------------------------------------------
+
+/**
+ * An acceptor that provides a TCPSocket for each accepted connection
+ */
+class TCPAcceptor : public Completer,
+                    public BufferedStreamAcceptor
+{
+private:
+    /**
+     * The accepted socket.
+     */
+    HANDLE acceptedSocket;
+
+private:
+    /**
+     * Construct the acceptor.
+     */
+    TCPAcceptor(TCPServerSocketBase* socket);
+
+    /**
+     * Get the socket.
+     *
+     * It returns the overlappable from the Completer part, knowing
+     * that it must be a TCPServerSocket.
+     */
+    TCPServerSocketBase& getServerSocket() const;
+
+public:
+    /**
+     * Try to accept a connection.
+     *
+     * If one is already accepted, but not retrieved yet, return true.
+     *
+     * If a new connection becomes immediately available, return true.
+     *
+     * If a new connection is not yet available, returns false.
+     *
+     * If some error occurs, the acceptor is marked failed and false
+     * is returned.
+     */
+    bool accept();
+
+    /**
+     * Get the TCP socket accepted last. If no socket was accepted,
+     * return 0. The TCP socket's waiter will be the given one
+     * (which can be 0).
+     */
+    TCPSocket* getSocket(Waiter* waiter,
+                         size_t readingCapacity = TCPSocket::DEFAULT_CAPACITY,
+                         size_t writingCapacity = TCPSocket::DEFAULT_CAPACITY);
+    /**
+     * Get the TCP socket accepted last. If no socket was accepted,
+     * return 0. The TCP socket's waiter will be the same as that of
+     * the associated server socket.
+     */
+    TCPSocket* getSocket(size_t readingCapacity = TCPSocket::DEFAULT_CAPACITY,
+                         size_t writingCapacity = TCPSocket::DEFAULT_CAPACITY);
+
+    /**
+     * Get the last accepted socket as a buffered stream with the given waiter,
+     * if any.
+     */
+    BufferedStream* getAcceptedBufferedStream(Waiter* waiter = nullptr) override;
+
+protected:
+    /**
+     * Set the indicator of an accepted connection to true.
+     *
+     * @see Completer::handleWaitedResult
+     */
+    void handleWaitedResult(DWORD size) override;
+
+    friend class TCPServerSocket;
+};
+
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline TCPAcceptor::TCPAcceptor(TCPServerSocketBase* socket) :
+    Completer(socket),
+    acceptedSocket(WSAInterface::get().getInvalidSocket())
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPServerSocketBase& TCPAcceptor::getServerSocket() const
+{
+    return static_cast<TCPServerSocketBase&>(overlappable);
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPSocket* TCPAcceptor::getSocket(Waiter* waiter,
+                                         size_t readingCapacity,
+                                         size_t writingCapacity)
+{
+    if (acceptedSocket==WSAInterface::get().getInvalidSocket()) return 0;
+
+    TCPSocket* socket = new TCPSocket(acceptedSocket, waiter,
+                                      readingCapacity, writingCapacity);
+    acceptedSocket = WSAInterface::get().getInvalidSocket();
+    return socket;
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPSocket* TCPAcceptor::getSocket(size_t readingCapacity,
+                                         size_t writingCapacity)
+{
+    return getSocket(overlappable.getWaiter(), readingCapacity, writingCapacity);
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.cc	(revision 30)
@@ -0,0 +1,66 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "TCPClientSocket.h"
+
+#include "WSAInterface.h"
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::TCPClientSocket;
+
+//------------------------------------------------------------------------------
+
+struct in_addr TCPClientSocket::str2address(const char* addressStr)
+{
+    struct in_addr address;
+    address.s_addr = inet_addr(addressStr);
+    return address;
+}
+
+//------------------------------------------------------------------------------
+
+TCPClientSocket::TCPClientSocket(struct in_addr address, unsigned short port,
+                                 Waiter* waiter,
+                                 size_t readingCapacity,
+                                 size_t writingCapacity) :
+    TCPSocket(WSAInterface::get().socket(AF_INET, SOCK_STREAM, 0), waiter,
+              readingCapacity, writingCapacity),
+    connector(this, address, port)
+{
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPClientSocket.h	(revision 30)
@@ -0,0 +1,128 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "TCPConnector.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * Client socket that connects to a TCP server socket.
+ *
+ * The server socket's address and port should be given.
+ */
+class TCPClientSocket : public TCPSocket
+{
+public:
+    /**
+     * Convert the given string to an address
+     */
+    static struct in_addr str2address(const char* addressStr);
+
+private:
+    /**
+     * The address to use for connecting.
+     */
+    TCPConnector connector;
+
+public:
+    /**
+     * Construct the client socket with the given address and port.
+     *
+     * @param waiter the waiter to use for waiting a possible event
+     * occuring on the socket. If given, the socket will be
+     * non-blocking. Otherwise, it will be blocking, and the connect()
+     * function of the Connector might block as well as the reading
+     * and writing buffers.
+     */
+    TCPClientSocket(struct in_addr address, unsigned short port,
+                    Waiter* waiter = 0,
+                    size_t readingCapacity = DEFAULT_CAPACITY,
+                    size_t writingCapacity = DEFAULT_CAPACITY);
+
+    /**
+     * Construct the client socket with the given address and port.
+     *
+     * @param waiter the waiter to use for waiting a possible event
+     * occuring on the socket. If given, the socket will be
+     * non-blocking. Otherwise, it will be blocking, and the connect()
+     * function of the Connector might block as well as the reading
+     * and writing buffers.
+     */
+    TCPClientSocket(const char* address, unsigned short port,
+                    Waiter* waiter = 0,
+                    size_t readingCapacity = DEFAULT_CAPACITY,
+                    size_t writingCapacity = DEFAULT_CAPACITY);
+
+    /**
+     * Get the connector for this client.
+     */
+    TCPConnector& getConnector();
+
+    friend class TCPConnector;
+};
+
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline TCPClientSocket::TCPClientSocket(const char* address, unsigned short port,
+                                        Waiter* waiter,
+                                        size_t readingCapacity,
+                                        size_t writingCapacity) :
+    TCPClientSocket(str2address(address), port, waiter,
+                    readingCapacity, writingCapacity)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPConnector& TCPClientSocket::getConnector()
+{
+    return connector;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPConnector.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPConnector.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPConnector.cc	(revision 30)
@@ -0,0 +1,82 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "TCPConnector.h"
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::TCPConnector;
+
+//------------------------------------------------------------------------------
+
+bool TCPConnector::connect()
+{
+    if (connected) return true;
+    if (failed()) return false;
+
+    bool result = false;
+    if (checkWaitedResult(result)) {
+        return result;
+    }
+
+    if (overlapped!=0) {
+        overlapped->reset();
+        socket.setNonBlocking(*overlapped, FD_CONNECT|FD_CLOSE);
+    }
+
+    if (socket.connect(address)) {
+        connected = true;
+        return true;
+    } else {
+        if (!socket.failed()) {
+            if (overlapped!=0) {
+                socket.addToWaiter(*overlapped);
+            }
+        }
+        return false;
+    }
+}
+
+//------------------------------------------------------------------------------
+
+void TCPConnector::handleWaitedResult(DWORD size)
+{
+    connected = true;
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPConnector.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPConnector.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPConnector.h	(revision 30)
@@ -0,0 +1,123 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "Completer.h"
+
+#include "TCPSocket.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * The connector class used by the TCP client socket.
+ */
+class TCPConnector : public Completer
+{
+private:
+    /**
+     * The local socket to connect on behalf of which we connect.
+     */
+    TCPSocket& socket;
+
+    /**
+     * The socket address to connect to.
+     */
+    struct sockaddr_in address;
+
+    /**
+     * Indicate if we are connected.
+     */
+    bool connected;
+
+    /**
+     * Indicate if we are connecting.
+     */
+    bool connecting;
+
+protected:
+    /**
+     * Create the connector for the given TCP client socket.
+     */
+    TCPConnector(TCPSocket* socket,
+                 struct in_addr address, unsigned short port);
+
+public:
+    /**
+     * Connect to an address properly set up.
+     *
+     * If the connection succeeds immediately, it indicates success.
+     *
+     * If the connection does not succeed, because it would block, it
+     * sets up the socket to wait for the connection to succeed, and
+     * returns failure.
+     *
+     * If the connection fails for another reason, the error code is
+     * set, and false is returned.
+     */
+    bool connect();
+
+private:
+
+    void handleWaitedResult(DWORD size) override;
+
+    friend class FailableReference<TCPConnector>;
+    friend class TCPClientSocket;
+};
+
+//------------------------------------------------------------------------------
+
+inline TCPConnector::TCPConnector(TCPSocket* socket,
+                                  struct in_addr address, unsigned short port) :
+    Completer(socket),
+    socket(*socket),
+    connected(false),
+    connecting(false)
+{
+    this->address.sin_family = AF_INET;
+    this->address.sin_addr = address;
+    this->address.sin_port = htons(port);
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.cc	(revision 30)
@@ -0,0 +1,73 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include "WSAInterface.h"
+#include "TCPServerSocket.h"
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::TCPServerSocket;
+
+//------------------------------------------------------------------------------
+
+TCPServerSocket::TCPServerSocket(unsigned short port, Waiter* waiter) :
+    TCPServerSocketBase(waiter,
+                        reinterpret_cast<HANDLE>(WSAInterface::get().socket(AF_INET, SOCK_STREAM, 0))),
+    acceptor(this)
+{
+    struct sockaddr_in sin;
+    sin.sin_family = AF_INET;
+    sin.sin_addr.s_addr = INADDR_ANY;
+    sin.sin_port = htons(port);
+
+    if (WSAInterface::get().bind(handle,
+                                 reinterpret_cast<struct sockaddr*>(&sin), sizeof(sin))<0) {
+        printf("TCPServerSocket: bind failed\n");
+        setErrorCode(GetLastError());
+        return;
+    }
+
+    if (WSAInterface::get().listen(handle)<0) {
+        printf("TCPServerSocket: listen failed\n");
+        setErrorCode(GetLastError());
+        return;
+    }
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPServerSocket.h	(revision 30)
@@ -0,0 +1,93 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "TCPServerSocketBase.h"
+
+#include "TCPAcceptor.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * A server socket that provides a TCP access point.
+ */
+class TCPServerSocket : public TCPServerSocketBase
+{
+private:
+    /**
+     * The acceptor to use for accepting connections
+     */
+    TCPAcceptor acceptor;
+
+public:
+    /**
+     * Construct the server socket to listen at the given port.
+     *
+     * @param port the number of the port to listen at
+     * @param waiter the waiter to use for waiting a possible event
+     * occuring on the socket. If given, the socket will be
+     * non-blocking. Otherwise, it will be blocking, and the accept()
+     * function of the Acceptor might block.
+     */
+    TCPServerSocket(unsigned short port, Waiter* waiter = nullptr);
+
+    /**
+     * Get the acceptor.
+     */
+    TCPAcceptor& getAcceptor();
+
+    friend class TCPAcceptor;
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline TCPAcceptor& TCPServerSocket::getAcceptor()
+{
+    return acceptor;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPServerSocketBase.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPServerSocketBase.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPServerSocketBase.h	(revision 30)
@@ -0,0 +1,110 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "Overlappable.h"
+#include "SocketMixin.h"
+#include "SocketEventFactory.h"
+#include "Event.h"
+
+#include <cstdio>
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+class Overlapped;
+
+//------------------------------------------------------------------------------
+
+/**
+ * A server socket that provides a TCP access point. This is here only to allow
+ * for a more efficient implementation of TCPAcceptor.
+ */
+class TCPServerSocketBase : public SocketMixin<Overlappable>
+{
+public:
+    /**
+     * Construct the server socket to listen at the given port.
+     *
+     * @param port the number of the port to listen at
+     * @param waiter the waiter to use for waiting a possible event
+     * occuring on the socket. If given, the socket will be
+     * non-blocking. Otherwise, it will be blocking, and the accept()
+     * function of the Acceptor might block.
+     */
+    TCPServerSocketBase(Waiter* waiter, HANDLE handle = 0);
+
+    /**
+     * Accept an incoming connection if possible.
+     */
+    HANDLE accept();
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline TCPServerSocketBase::TCPServerSocketBase(Waiter* waiter,
+                                                HANDLE handle) :
+    SocketMixin<Overlappable>(std::make_unique<SocketEventFactory>(),
+                              waiter, handle)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline HANDLE TCPServerSocketBase::accept()
+{
+    auto a = WSAInterface::get().accept(handle);
+    if (WSAInterface::get().isInvalidSocket(a)) {
+        auto lastError = GetLastError();
+        if (lastError!=WSAEWOULDBLOCK && lastError!=WSAEINPROGRESS) {
+            setErrorCode(lastError);
+        }
+    }
+
+    return a;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/TCPSocket.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/TCPSocket.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/TCPSocket.h	(revision 30)
@@ -0,0 +1,141 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include "WSAInterface.h"
+
+#include "BufferedStream.h"
+#include "SocketMixin.h"
+#include "SocketEventFactory.h"
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * A socket that works on a TCP connection.
+ */
+class TCPSocket : public SocketMixin<BufferedStream>
+{
+protected:
+    /**
+     * Construct the TCP socket.
+     */
+    TCPSocket(Waiter* waiter = 0, int protocol = 0,
+              size_t readingCapacity = DEFAULT_CAPACITY,
+              size_t writingCapacity = DEFAULT_CAPACITY);
+
+    /**
+     * Construct the socket with the given parameters.
+     */
+    TCPSocket(HANDLE s, Waiter* waiter = 0,
+              size_t readingCapacity = DEFAULT_CAPACITY,
+              size_t writingCapacity = DEFAULT_CAPACITY);
+
+public:
+    /**
+     * Destroy the socket by closing the file descriptor
+     */
+    ~TCPSocket();
+
+protected:
+    /**
+     * Connect the client socket to the server.
+     */
+    bool connect(const struct sockaddr_in& sin);
+
+    friend class TCPAcceptor;
+    friend class TCPConnector;
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline TCPSocket::TCPSocket(Waiter* waiter, int protocol,
+                            size_t readingCapacity,
+                            size_t writingCapacity) :
+    TCPSocket(WSAInterface::get().socket(AF_INET, SOCK_STREAM, protocol),
+              waiter, readingCapacity, writingCapacity)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPSocket::TCPSocket(HANDLE s, Waiter* waiter,
+                            size_t readingCapacity,
+                            size_t writingCapacity) :
+    SocketMixin<BufferedStream>(std::make_unique<SocketEventFactory>(),
+                                waiter, s,
+                                readingCapacity, writingCapacity)
+{
+}
+
+//------------------------------------------------------------------------------
+
+inline TCPSocket::~TCPSocket()
+{
+    if (!WSAInterface::get().isInvalidSocket(handle)) {
+        WSAInterface::get().closesocket(handle);
+    }
+}
+
+
+//------------------------------------------------------------------------------
+
+inline bool TCPSocket::connect(const struct sockaddr_in& sin)
+{
+    auto a = WSAInterface::get().connect(handle,
+                                         reinterpret_cast<const struct sockaddr*>(&sin),
+                                         sizeof(sin));
+    if (a==SOCKET_ERROR) {
+        auto lastError = GetLastError();
+        if (lastError!=WSAEWOULDBLOCK && lastError!=WSAEINPROGRESS) {
+            setErrorCode(lastError);
+        }
+    }
+
+    return a!=SOCKET_ERROR;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/WSAInterface.cc
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/WSAInterface.cc	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/WSAInterface.cc	(revision 30)
@@ -0,0 +1,125 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+//------------------------------------------------------------------------------
+
+#include <winsock2.h>
+
+#include "WSAInterface.h"
+
+//------------------------------------------------------------------------------
+
+using hu::varadiistvan::scpl::io::WSAInterface;
+
+//------------------------------------------------------------------------------
+
+WSAInterface::WSAInterface()
+{
+    WSADATA wsaData;
+    WSAStartup(MAKEWORD(2, 2), &wsaData);
+}
+
+//------------------------------------------------------------------------------
+
+WSAInterface::~WSAInterface()
+{
+    WSACleanup();
+}
+
+//------------------------------------------------------------------------------
+
+HANDLE WSAInterface::getInvalidSocket()
+{
+    return reinterpret_cast<HANDLE>(INVALID_SOCKET);
+}
+
+//------------------------------------------------------------------------------
+
+bool WSAInterface::isInvalidSocket(HANDLE handle)
+{
+    return handle==reinterpret_cast<HANDLE>(INVALID_SOCKET);
+}
+
+//------------------------------------------------------------------------------
+
+HANDLE WSAInterface::socket(int af, int type, int protocol)
+{
+    return reinterpret_cast<HANDLE>(::socket(af, type, protocol));
+}
+
+//------------------------------------------------------------------------------
+
+int WSAInterface::eventSelect(HANDLE socket, HANDLE event, long eventMask)
+{
+    return WSAEventSelect(reinterpret_cast<SOCKET>(socket),
+                          event, eventMask);
+}
+
+//------------------------------------------------------------------------------
+
+int WSAInterface::bind(HANDLE socket, const struct sockaddr* name, int namelen)
+{
+    return ::bind(reinterpret_cast<SOCKET>(socket), name, namelen);
+}
+
+//------------------------------------------------------------------------------
+
+int WSAInterface::listen(HANDLE socket, int backlog)
+{
+    return ::listen(reinterpret_cast<SOCKET>(socket), backlog);
+}
+
+//------------------------------------------------------------------------------
+
+HANDLE WSAInterface::accept(HANDLE socket, struct sockaddr* addr, int* addrlen)
+{
+    return reinterpret_cast<HANDLE>(::accept(reinterpret_cast<SOCKET>(socket),
+                                             addr, addrlen));
+}
+
+//------------------------------------------------------------------------------
+
+int WSAInterface::connect(HANDLE socket, const struct sockaddr* name, int namelen)
+{
+    return ::connect(reinterpret_cast<SOCKET>(socket), name, namelen);
+}
+
+//------------------------------------------------------------------------------
+
+int WSAInterface::closesocket(HANDLE socket)
+{
+    return ::closesocket(reinterpret_cast<SOCKET>(socket));
+}
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
Index: src/hu/varadiistvan/scpl/io/_win32/WSAInterface.h
===================================================================
--- src/hu/varadiistvan/scpl/io/_win32/WSAInterface.h	(revision 30)
+++ src/hu/varadiistvan/scpl/io/_win32/WSAInterface.h	(revision 30)
@@ -0,0 +1,134 @@
+// Copyright (c) 2022 by István Váradi
+
+// This file is part of VSCPL, a simple cross-platform utility library
+
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The views and conclusions contained in the software and documentation are those
+// of the authors and should not be interpreted as representing official policies,
+// either expressed or implied, of the FreeBSD Project.
+
+#pragma once
+
+//------------------------------------------------------------------------------
+
+#include <windows.h>
+
+//------------------------------------------------------------------------------
+
+namespace hu { namespace varadiistvan { namespace scpl { namespace io {
+
+//------------------------------------------------------------------------------
+
+/**
+ * An object to access the WSA functions through it. It is a singleton, and its
+ * constructor initializes the WSA subsystem, while its destructor cleans it
+ * up.
+ */
+class WSAInterface
+{
+public:
+    /**
+     * Get the only instance of this class
+     */
+    static WSAInterface& get();
+
+private:
+    /**
+     * Construct the interface.
+     */
+    WSAInterface();
+
+    /**
+     * Destroy the interface.
+     */
+    ~WSAInterface();
+
+public:
+    /**
+     * Get the invalid socket handle as a HANDLE.
+     */
+    HANDLE getInvalidSocket();
+
+    /**
+     * Determine if the given handle represents an invalid socket.
+     */
+    bool isInvalidSocket(HANDLE handle);
+
+    /**
+     * Create a socket.
+     */
+    HANDLE socket(int af, int type, int protocol);
+
+    /**
+     * Set the given socket into non-blocking mode and make the given event to
+     * be triggered by the events in the given event mask
+     */
+    int eventSelect(HANDLE socket, HANDLE event, long eventMask);
+
+    /**
+     * Bind the given socket handle to the given address.
+     */
+    int bind(HANDLE socket, const struct sockaddr* name, int namelen);
+
+    /**
+     * Start listening on the given socket.
+     */
+    int listen(HANDLE socket, int backlog = 5);
+
+    /**
+     * Accept a socket on the given server socket.
+     */
+    HANDLE accept(HANDLE socket,
+                  struct sockaddr* addr = nullptr, int* addrlen = nullptr);
+
+    /**
+     * Try to connect to the given address using the given socket.
+     */
+    int connect(HANDLE socket, const struct sockaddr* name, int namelen);
+
+    /**
+     * Close the givern socket.
+     */
+    int closesocket(HANDLE socket);
+};
+
+//------------------------------------------------------------------------------
+// Inline definitions
+//------------------------------------------------------------------------------
+
+inline WSAInterface& WSAInterface::get()
+{
+    static WSAInterface wsa;
+    return wsa;
+}
+
+//------------------------------------------------------------------------------
+
+} /* namespace hu::varadiistvan::scpl::io */ } /* namespace hu::varadiistvan::scpl */ } /* namespace hu::varadiistvan */ } /* namespace hu */
+
+//------------------------------------------------------------------------------
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 4
+// indent-tabs-mode: nil
+// End:
