Add rudimentary networking abilities

This commit is contained in:
Jaculabilis 2017-09-23 21:06:47 -05:00
parent 5dee4d971c
commit d400883be1
12 changed files with 223 additions and 32 deletions

View File

@ -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")

43
src/Fishtank.py Normal file
View File

@ -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
src/__init__.py Normal file
View File

25
src/entity/Entity.py Normal file
View File

@ -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

22
src/entity/Tube.py Normal file
View File

@ -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
src/entity/__init__.py Normal file
View File

View File

@ -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))

View File

@ -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))

View File

View File

@ -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
src/network/__init__.py Normal file
View File

54
src/server.py Normal file
View File

@ -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()