Add rudimentary networking abilities
This commit is contained in:
parent
5dee4d971c
commit
d400883be1
32
server.py
32
server.py
|
@ -1,32 +0,0 @@
|
||||||
import sys
|
|
||||||
import zmq
|
|
||||||
import time
|
|
||||||
|
|
||||||
if sys.argv[1] == "send":
|
|
||||||
PORT = int(sys.argv[2])
|
|
||||||
DEST = int(sys.argv[3])
|
|
||||||
sys.stdout.write("Using port {}\n".format(PORT))
|
|
||||||
sys.stdout.write("Connecting to port {}\n".format(DEST))
|
|
||||||
|
|
||||||
context = zmq.Context()
|
|
||||||
socket = context.socket(zmq.REQ)
|
|
||||||
socket.connect("tcp://localhost:{}".format(DEST))
|
|
||||||
|
|
||||||
while True:
|
|
||||||
socket.send(b"Gentlemen.")
|
|
||||||
message = socket.recv()
|
|
||||||
sys.stdout.write("Response: {}\n".format(message))
|
|
||||||
|
|
||||||
if sys.argv[1] == "recv":
|
|
||||||
PORT = int(sys.argv[2])
|
|
||||||
sys.stdout.write("Using port {}\n".format(PORT))
|
|
||||||
|
|
||||||
context = zmq.Context()
|
|
||||||
socket = context.socket(zmq.REP)
|
|
||||||
socket.bind("tcp://*:{}".format(PORT))
|
|
||||||
|
|
||||||
while True:
|
|
||||||
message = socket.recv()
|
|
||||||
sys.stdout.write("Received message: {}\n".format(message))
|
|
||||||
time.sleep(1)
|
|
||||||
socket.send(b"Received")
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
class Fishtank():
|
||||||
|
def __init__(self, recv_queue):
|
||||||
|
self._entities = []
|
||||||
|
self._to_remove = []
|
||||||
|
self._recv_queue = recv_queue
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
# Delete flagged entities
|
||||||
|
if self._to_remove:
|
||||||
|
for entity in self._to_remove:
|
||||||
|
self._entities.remove(entity)
|
||||||
|
self._to_remove = []
|
||||||
|
# Update and draw
|
||||||
|
for entity in self._entities:
|
||||||
|
entity.update()
|
||||||
|
for entity in self._entities:
|
||||||
|
entity.draw()
|
||||||
|
#time.sleep(1)
|
||||||
|
# Intake queue
|
||||||
|
if not self._recv_queue.empty():
|
||||||
|
serial = self._recv_queue.get(False)
|
||||||
|
sys.stdout.write("Fishtank dequeued a {}\n".format(serial["class"]))
|
||||||
|
mod = __import__(serial["module"], fromlist=[serial["class"]])
|
||||||
|
klass = getattr(mod, serial["class"])
|
||||||
|
e = klass.deserialize(serial)
|
||||||
|
self.add_entity(e)
|
||||||
|
|
||||||
|
def add_entity(self, entity):
|
||||||
|
entity._fishtank = self
|
||||||
|
self._entities.append(entity)
|
||||||
|
sys.stdout.write("Added: {}\n".format(repr(entity)))
|
||||||
|
|
||||||
|
def remove_entity(self, entity):
|
||||||
|
if entity not in self._entities:
|
||||||
|
sys.stderr.write(
|
||||||
|
"WARN: remove called for entity '{}', but it isn't in the eneityt list\n".format(entity.__name__))
|
||||||
|
return
|
||||||
|
self._to_remove.append(entity)
|
|
@ -0,0 +1,25 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class Entity(object):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[Entity]"
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
return {
|
||||||
|
"module":"entity.Entity",
|
||||||
|
"class":"Entity"
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def deserialize(serial):
|
||||||
|
e = Entity()
|
||||||
|
return e
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
pass
|
|
@ -0,0 +1,22 @@
|
||||||
|
import sys
|
||||||
|
from entity.Entity import Entity
|
||||||
|
|
||||||
|
class Tube(Entity):
|
||||||
|
def __init__(self, network_gate):
|
||||||
|
Entity.__init__(self)
|
||||||
|
self._gate = network_gate
|
||||||
|
self._inbox = []
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[Tube gate={} inbox={}]".format(repr(self._gate), repr(self._inbox))
|
||||||
|
|
||||||
|
def accept(self, entity):
|
||||||
|
self._fishtank.remove_entity(entity)
|
||||||
|
self._inbox.append(entity)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
Entity.update(self)
|
||||||
|
if self._inbox:
|
||||||
|
entity = self._inbox.pop(0)
|
||||||
|
sys.stdout.write("Sending: {}\n".format(repr(entity)))
|
||||||
|
self._gate.transmit(entity.serialize())
|
|
@ -0,0 +1,41 @@
|
||||||
|
import sys
|
||||||
|
from entity.Entity import Entity
|
||||||
|
from entity.Tube import Tube
|
||||||
|
|
||||||
|
class DebugJumper(Entity):
|
||||||
|
def __init__(self, message):
|
||||||
|
Entity.__init__(self)
|
||||||
|
self._message = message
|
||||||
|
self._counter = 0
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[DebugJumper message='{}' counter={}]".format(self._message, self._counter)
|
||||||
|
|
||||||
|
def serialize(self):
|
||||||
|
sup = Entity.serialize(self)
|
||||||
|
sup.update({
|
||||||
|
"module":"entity.dummy.DebugJumper",
|
||||||
|
"class":"DebugJumper",
|
||||||
|
"message":self._message,
|
||||||
|
"counter":self._counter
|
||||||
|
})
|
||||||
|
return sup
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def deserialize(serial):
|
||||||
|
e = DebugJumper(serial["message"])
|
||||||
|
e._counter = serial["counter"]
|
||||||
|
return e
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
Entity.update(self)
|
||||||
|
self._counter += 1
|
||||||
|
if self._counter % 5 == 0:
|
||||||
|
for entity in self._fishtank._entities:
|
||||||
|
if type(entity) is Tube:
|
||||||
|
entity.accept(self)
|
||||||
|
break
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
Entity.draw(self)
|
||||||
|
sys.stdout.write(self._message + " ({})\n".format(self._counter))
|
|
@ -0,0 +1,19 @@
|
||||||
|
import sys
|
||||||
|
from entity.Entity import Entity
|
||||||
|
|
||||||
|
class DebugWaiter(Entity):
|
||||||
|
def __init__(self, message):
|
||||||
|
Entity.__init__(self)
|
||||||
|
self._message = message
|
||||||
|
self._counter = 0
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[DebugWaiter message='{}' counter={}]".format(self._message, self._counter)
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
Entity.update(self)
|
||||||
|
self._counter += 1
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
Entity.draw(self)
|
||||||
|
sys.stdout.write(self._message + " ({})\n".format(self._counter))
|
|
@ -0,0 +1,19 @@
|
||||||
|
import sys
|
||||||
|
import zmq
|
||||||
|
import json
|
||||||
|
|
||||||
|
class NetworkGate():
|
||||||
|
def __init__(self, address, port):
|
||||||
|
self._address = address
|
||||||
|
self._port = port
|
||||||
|
context = zmq.Context()
|
||||||
|
self._socket = context.socket(zmq.REQ)
|
||||||
|
self._socket.connect("tcp://{}:{}".format(address, port))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[NetworkGate {}:{}]".format(self._address, self._port)
|
||||||
|
|
||||||
|
def transmit(self, serial):
|
||||||
|
s = json.dumps(serial)
|
||||||
|
self._socket.send_string(s)
|
||||||
|
message = self._socket.recv()
|
|
@ -0,0 +1,54 @@
|
||||||
|
import sys
|
||||||
|
import zmq
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from multiprocessing import Process, Queue
|
||||||
|
from Fishtank import Fishtank
|
||||||
|
|
||||||
|
def socket_listener(port, recv_queue):
|
||||||
|
sys.stdout.write("Socket listener starting...\n")
|
||||||
|
context = zmq.Context()
|
||||||
|
socket = context.socket(zmq.REP)
|
||||||
|
socket.bind("tcp://*:{}".format(port))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
message = socket.recv()
|
||||||
|
response = b"Undefined response"
|
||||||
|
try:
|
||||||
|
serial = json.loads(message)
|
||||||
|
if "class" in serial:
|
||||||
|
sys.stdout.write("Listener received a {}\n".format(serial["class"]))
|
||||||
|
recv_queue.put(serial, False)
|
||||||
|
response = b"Received"
|
||||||
|
except:
|
||||||
|
response = b"Error"
|
||||||
|
socket.send(response)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
port = int(sys.argv[1])
|
||||||
|
sys.stdout.write("Launching on port {}\n".format(port))
|
||||||
|
# Spawn the socket thread
|
||||||
|
q = Queue()
|
||||||
|
socket_proc = Process(target=socket_listener, args=(port,q))
|
||||||
|
socket_proc.start()
|
||||||
|
sys.stdout.write("Socket thread started\n")
|
||||||
|
time.sleep(1)
|
||||||
|
# Build the world
|
||||||
|
fishtank = Fishtank(q)
|
||||||
|
for i in range(1, len(sys.argv)):
|
||||||
|
if sys.argv[i] == "-w":
|
||||||
|
from entity.dummy.DebugWaiter import DebugWaiter
|
||||||
|
fishtank.add_entity(DebugWaiter("DebugWaiter"))
|
||||||
|
if sys.argv[i] == "-j":
|
||||||
|
from entity.dummy.DebugJumper import DebugJumper
|
||||||
|
fishtank.add_entity(DebugJumper("DebugJumper"))
|
||||||
|
if sys.argv[i] == "-t":
|
||||||
|
pipe_port = int(sys.argv[i+1])
|
||||||
|
from network.NetworkGate import NetworkGate
|
||||||
|
network_gate = NetworkGate("localhost", pipe_port)
|
||||||
|
from entity.Tube import Tube
|
||||||
|
fishtank.add_entity(Tube(network_gate))
|
||||||
|
fishtank.run()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue