Twisted
은 프로토콜 구현에 더 적합하다고 생각합니다. 어쨌든, 파이썬에서 함수와 메소드는 퍼스트 클래스의 객체이므로 사전에 저장할 수 있습니다. functools.partial
을 사용하여 인수가있는 함수를 사전 키에 바인딩 할 수도 있습니다. 전환을 구현하는 데 사용할 수 있습니다. 각 상태는 키가 가능한 입력 상태이고 값은 출력 상태 인 사전을 포함하는 함수 여야합니다. 그러면 한 국가에서 다른 국가로 쉽게 넘어갈 수 있습니다. Tornado 루프를 사용하려면 다음 상태를 직접 호출하는 대신 ioloop.IOLoop.instance().add_callback
을 사용하여 콜백으로 등록해야합니다.
오토마타 언어에게 B 형 * * C를 접수 구현 예 :
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"
세션 netcat을 사용 : 질문
$ 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 더 나은가요? –