私はTwisted
がプロトコルの実装により適していると思います。とにかく、Pythonの関数とメソッドは、ファーストクラスのオブジェクトであり、辞書の内部に格納することができます。 functools.partial
を使用して、引数を持つ関数を辞書キーにバインドすることもできます。これを使ってトランジションを実装することができます。各状態は、キーが可能な入力状態であり、値が出力状態である辞書を含む関数でなければならない。その後、ある州から別の州に簡単にフープすることができます。 Tornadoループを使用するには、直接呼び出さずにioloop.IOLoop.instance().add_callback
を使用してコールバックとして登録する必要があります。
オートマトン受諾言語の実装例a * b *表C:Netcatをを使用して
import errno
import functools
import socket
from tornado import ioloop, iostream
class Communicator(object):
def connection_ready(self, sock, fd, events):
while True:
try:
connection, address = sock.accept()
except socket.error, e:
if e[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
raise
return
connection.setblocking(0)
self.stream = iostream.IOStream(connection)
self.stream.read_until(delimiter='\n', callback=self.initial_state)
def initial_state(self, msg):
msg = msg.rstrip()
print "entering initial state with message: %s" % msg
transitions = {
'a' : functools.partial(ioloop.IOLoop.instance().add_callback, self.state_a, msg),
'b' : functools.partial(ioloop.IOLoop.instance().add_callback, self.state_b, msg),
'c' : functools.partial(ioloop.IOLoop.instance().add_callback, self.final_state, msg)
}
try:
transitions[msg[0]]()
except:
self.stream.write("Aborted (wrong input)\n", self.stream.close)
def state_a(self, msg):
print "entering state a with message: %s" % msg
transitions = {
'a' : functools.partial(ioloop.IOLoop.instance().add_callback, self.stream.write, "got a\n", functools.partial(self.state_a, msg[1:])),
'b' : functools.partial(ioloop.IOLoop.instance().add_callback, self.state_b, msg),
'c' : functools.partial(ioloop.IOLoop.instance().add_callback, self.final_state, msg[1:])
}
try:
transitions[msg[0]]()
except:
self.stream.write("Aborted (wrong input)\n", self.stream.close)
def state_b(self, msg):
print "entering state b with message: %s" % msg
transitions = {
'a' : functools.partial(ioloop.IOLoop.instance().add_callback, self.state_a, msg),
'b' : functools.partial(ioloop.IOLoop.instance().add_callback, self.stream.write, "got b\n", functools.partial(self.state_a, msg[1:])),
'c' : functools.partial(ioloop.IOLoop.instance().add_callback, self.final_state, msg[1:])}
try:
transitions[msg[0]]()
except:
self.stream.write("Aborted (wrong input)\n" , self.stream.close)
def final_state(self, msg):
print "entering final state with message: %s" % msg
self.stream.write("Finished properly with message %s\n" % msg, self.stream.close)
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setblocking(0)
sock.bind(("", 8000))
sock.listen(5000)
communicator = Communicator()
io_loop = ioloop.IOLoop.instance()
callback = functools.partial(communicator.connection_ready, sock)
io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
try:
io_loop.start()
except KeyboardInterrupt:
io_loop.stop()
print "exited cleanly"
はセッション:
$ nc localhost 8000
aaaaa
got a
got a
got a
got a
got a
Aborted (wrong input)
$ nc localhost 8000
abababab
got a
got b
got a
got b
got a
got b
got a
got b
Aborted (wrong input)
$ nc localhost 8000
aaabbbc
got a
got a
got a
got b
got b
got b
Finished properly with message
$ nc localhost 8000
abcabc
got a
got b
Finished properly with message abc
質問はありますか? – Veedrac
@Veedrac今は良いですか? –