UDP Echo server


from __future__ import print_function

import signal
import pyuv


def on_read(handle, ip_port, flags, data, error):
    if data is not None:
        handle.send(ip_port, data)

def signal_cb(handle, signum):
    signal_h.close()
    server.close()


print("PyUV version %s" % pyuv.__version__)

loop = pyuv.Loop.default_loop()

server = pyuv.UDP(loop)
server.bind(("0.0.0.0", 1234))
server.start_recv(on_read)

signal_h = pyuv.Signal(loop)
signal_h.start(signal_cb, signal.SIGINT)

loop.run()

print("Stopped!")

TCP Echo server


from __future__ import print_function

import signal
import pyuv


def on_read(client, data, error):
    if data is None:
        client.close()
        clients.remove(client)
        return
    client.write(data)

def on_connection(server, error):
    client = pyuv.TCP(server.loop)
    server.accept(client)
    clients.append(client)
    client.start_read(on_read)

def signal_cb(handle, signum):
    [c.close() for c in clients]
    signal_h.close()
    server.close()


print("PyUV version %s" % pyuv.__version__)

loop = pyuv.Loop.default_loop()
clients = []

server = pyuv.TCP(loop)
server.bind(("0.0.0.0", 1234))
server.listen(on_connection)

signal_h = pyuv.Signal(loop)
signal_h.start(signal_cb, signal.SIGINT)

loop.run()
print("Stopped!")

TCP Echo server using Poll handles


import sys
import socket
import signal
import weakref
import errno
import logging
import pyuv

logging.basicConfig(level=logging.DEBUG)

STOPSIGNALS = (signal.SIGINT, signal.SIGTERM)
NONBLOCKING = (errno.EAGAIN, errno.EWOULDBLOCK)
if sys.platform == "win32":
    NONBLOCKING = NONBLOCKING + (errno.WSAEWOULDBLOCK,)


class Connection(object):

    def __init__(self, sock, address, loop):
        self.sock = sock
        self.address = address
        self.sock.setblocking(0)
        self.buf = ""
        self.watcher = pyuv.Poll(loop, self.sock.fileno())
        self.watcher.start(pyuv.UV_READABLE, self.io_cb)
        logging.debug("{0}: ready".format(self))

    def reset(self, events):
        self.watcher.start(events, self.io_cb)

    def handle_error(self, msg, level=logging.ERROR, exc_info=True):
        logging.log(level, "{0}: {1} --> closing".format(self, msg), exc_info=exc_info)
        self.close()

    def handle_read(self):
        try:
            buf = self.sock.recv(1024)
        except socket.error as err:
            if err.args[0] not in NONBLOCKING:
                self.handle_error("error reading from {0}".format(self.sock))
        if buf:
            self.buf += buf
            self.reset(pyuv.UV_READABLE | pyuv.UV_WRITABLE)
        else:
            self.handle_error("connection closed by peer", logging.DEBUG, False)

    def handle_write(self):
        try:
            sent = self.sock.send(self.buf)
        except socket.error as err:
            if err.args[0] not in NONBLOCKING:
                self.handle_error("error writing to {0}".format(self.sock))
        else :
            self.buf = self.buf[sent:]
            if not self.buf:
                self.reset(pyuv.UV_READABLE)

    def io_cb(self, watcher, revents, error):
        if error is not None:
            logging.error("Error in connection: %d: %s" % (error, pyuv.errno.strerror(error)))
            return
        if revents & pyuv.UV_READABLE:
            self.handle_read()
        elif revents & pyuv.UV_WRITABLE:
            self.handle_write()

    def close(self):
        self.watcher.stop()
        self.watcher = None
        self.sock.close()
        logging.debug("{0}: closed".format(self))


class Server(object):

    def __init__(self, address):
        self.sock = socket.socket()
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(address)
        self.sock.setblocking(0)
        self.address = self.sock.getsockname()
        self.loop = pyuv.Loop.default_loop()
        self.poll_watcher = pyuv.Poll(self.loop, self.sock.fileno())
        self.async = pyuv.Async(self.loop, self.async_cb)
        self.conns = weakref.WeakValueDictionary()
        self.signal_watchers = set()

    def handle_error(self, msg, level=logging.ERROR, exc_info=True):
        logging.log(level, "{0}: {1} --> stopping".format(self, msg), exc_info=exc_info)
        self.stop()

    def signal_cb(self, handle, signum):
        self.async.send()

    def async_cb(self, handle):
        handle.close()
        self.stop()

    def io_cb(self, watcher, revents, error):
        try:
            while True:
                try:
                    sock, address = self.sock.accept()
                except socket.error as err:
                    if err.args[0] in NONBLOCKING:
                        break
                    else:
                        raise
                else:
                    self.conns[address] = Connection(sock, address, self.loop)
        except Exception:
            self.handle_error("error accepting a connection")

    def start(self):
        self.sock.listen(socket.SOMAXCONN)
        self.poll_watcher.start(pyuv.UV_READABLE, self.io_cb)
        for sig in STOPSIGNALS:
            handle = pyuv.Signal(self.loop)
            handle.start(self.signal_cb, sig)
            self.signal_watchers.add(handle)
        logging.debug("{0}: started on {0.address}".format(self))
        self.loop.run()
        logging.debug("{0}: stopped".format(self))

    def stop(self):
        self.poll_watcher.stop()
        for watcher in self.signal_watchers:
            watcher.stop()
        self.signal_watchers.clear()
        self.sock.close()
        for conn in self.conns.values():
            conn.close()
        logging.debug("{0}: stopping".format(self))


if __name__ == "__main__":
    server = Server(("127.0.0.1", 9876))
    server.start()

Standard IO Echo server using Pipe handles

import signal
import sys
import pyuv


def on_pipe_read(handle, data, error):
    if data is None or data == b"exit":
        pipe_stdin.close()
        pipe_stdout.close()
    else:
        pipe_stdout.write(data)

def signal_cb(handle, signum):
    if not pipe_stdin.closed:
        pipe_stdin.close()
    if not pipe_stdin.closed:
        pipe_stdout.close()
    signal_h.close()


loop = pyuv.Loop.default_loop()

pipe_stdin = pyuv.Pipe(loop)
pipe_stdin.open(sys.stdin.fileno())
pipe_stdin.start_read(on_pipe_read)

pipe_stdout = pyuv.Pipe(loop)
pipe_stdout.open(sys.stdout.fileno())

signal_h = pyuv.Signal(loop)
signal_h.start(signal_cb, signal.SIGINT)

loop.run()

Standard IO Echo server using TTY handles


from __future__ import print_function

import signal
import sys
import pyuv


def on_tty_read(handle, data, error):
    if data is None or data == b"exit":
        tty_stdin.close()
        tty_stdout.close()
    else:
        tty_stdout.write(data)

def signal_cb(handle, signum):
    tty_stdin.close()
    tty_stdout.close()
    signal_h.close()


loop = pyuv.Loop.default_loop()

tty_stdin = pyuv.TTY(loop, sys.stdin.fileno(), True)
tty_stdin.start_read(on_tty_read)
tty_stdout = pyuv.TTY(loop, sys.stdout.fileno(), False)

if sys.platform != "win32":
    print("Window size: (%d, %d)" % tty_stdin.get_winsize())

signal_h = pyuv.Signal(loop)
signal_h.start(signal_cb, signal.SIGINT)

loop.run()

pyuv.TTY.reset_mode()