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