echo server written by asyncore.

Twistedにおされてかどうかは知りませんが、同じ目的で使用されるPython標準モジュールのasyncoreの情報が少ないので、ちょっと勉強がてらにメモを残そう、と。

クライアントからの文字列をそのまま返すEchoサーバ。

import asyncore, socket

HOST = ''
PORT = 6601
RECV_BUFSIZE = 4096
RECV_BUFSIZE = 10

class RequestHundler(asyncore.dispatcher):
    def __init__(self, sock):
        self.sendbuffer = ""
        asyncore.dispatcher.__init__(self, sock)

    def handle_read(self):
        data = self.recv(RECV_BUFSIZE)
        if not data: return
        print ">>>Receive from Pserver:?n%s" % data
        self.sendbuffer += data

    def writable(self):
        return (len(self.sendbuffer) > 0)

    def handle_write(self):
        n = self.send(self.sendbuffer)
        print "<<<Send    to   Pserver:?n%s" % self.sendbuffer
        self.sendbuffer = self.sendbuffer[n:]

    def handle_close(self):
        print "---Pserver connection close. (handle)"
        self.close()


class EchoServer(asyncore.dispatcher):
    def __init__(self, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind((HOST, port))
        self.listen(3)
        print "+++Listen to", HOST, port

    def handle_accept(self):
        conn, addr = self.accept()
        print conn, addr
        RequestHundler(conn)

    def handle_close(self):
        self.close()


if __name__ == '__main__':
    cli = EchoServer(PORT)
    while True:
        asyncore.loop()

次はクライアント。文字列流すだけですが。

import asyncore, socket, sys

PORT = 6601
RECV_BUF = 20

class EchoClient(asyncore.dispatcher):
    def __init__(self, host, data):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, PORT))
        self.buffer = data
        self.datalen = len(data)
        self.recvlen = 0

    def handle_read(self):
        data = self.recv(RECV_BUF)
        self.recvlen += len(data)
        if self.recvlen == self.datalen:
            self.close()
        print ">>>Receive from Server:?n%s" % data

    def writeable(self):
        return (len(self.buffer) > 0)

    def handle_write(self):
        n = self.send(self.buffer)
        if n:
            print "<<<Send    to   Server:?n%s" % self.buffer[:n]
        self.buffer = self.buffer[n:]

    def handle_close(self):
        self.close()


if __name__ == '__main__':
    strings = '0123456789' * 10
    cli = EchoClient(sys.argv[1], strings)
    asyncore.loop()


標準モジュールしか使えな状況が多いので、もう少しasyncoreを追っかけてみようと思います。
Twistedもおもしろそうですが。