[Moeng-cvs] Mamura/tests/netobjs NetObjects.rb,NONE,1.1 NetSessions.rb,NONE,1.1
Status: Alpha
Brought to you by:
b_lindeijer
From: <b_l...@us...> - 2004-03-04 18:09:08
|
Update of /cvsroot/moeng/Mamura/tests/netobjs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32227 Added Files: NetObjects.rb NetSessions.rb Log Message: Added implementation of ClanLib's network objects model. --- NEW FILE: NetObjects.rb --- # $Id: NetObjects.rb,v 1.1 2004/03/04 17:47:43 b_lindeijer Exp $ # The NetObjectController controls a group of network objects over a single # communications channel. Incoming messages are send through to the objects # they belong to. When at the client there is no such object, it is created. class NetObjectController attr_reader :channel def initialize(netsession, channel) @netsession = netsession @channel = channel @netsession.on_receive_call(channel, self) @next_obj_id = -1 @client_objs = Array.new @server_objs = Array.new end def on_receive(message, from) print("ObjectController received ", message, "\n") server_obj = message[0] obj_id = message[1] mess = message[2] # Message can be either from server or client if server_obj # Junk if object doesn't exist obj = @server_objs.at(obj_id) if obj obj.on_receive(from, mess) end else # Maybe we need to create it obj = @client_objs.at(obj_id) if obj obj.on_receive(mess) elsif @creator obj = NetObjectClient.new(obj_id, from, self) if @creator.on_create(obj, mess) @client_objs[obj_id] = obj end end end end def on_create_call(creator) @creator = creator end def next_obj_id @next_obj_id += 1 end end # A networked object at the client. It sends messages to its server # equivalent and dispatches incoming messages to the registered handler. class NetObjectClient attr_reader :obj_id def initialize(obj_id, server, controller) @obj_id = obj_id @server = server @controller = controller end def send(message) @server.send(@controller.channel, [true, @obj_id, message]) end def on_receive_call(handler) @handler = handler end def on_receive(message) end end # A networked object at the server. It can send messages to any group of # clients. Incoming messages are dispatches to the registered handler. class NetObjectServer attr_reader :obj_id def initialize(controller) @controller = controller @obj_id = controller.next_obj_id end def send(computers, message) computers.each { |comp| comp.send(@controller.channel, [false, @obj_id, message]) } end def on_receive_call(handler) @handler = handler end def on_receive(computer, message) end end --- NEW FILE: NetSessions.rb --- # $Id: NetSessions.rb,v 1.1 2004/03/04 17:47:43 b_lindeijer Exp $ # The network session. This class can function as a server to which clients can # connect or it can connect to a server itself, or both. class NetComputer attr_reader :netsession def initialize(tcp_socket, netsession) @tcp_socket = tcp_socket @netsession = netsession end def send(channel, message) # message is expected to be an array, but can in theory be any object # that can be used with the Marshal module print("Marshalling ", message, " to computer ") print(@tcp_socket.peeraddr[1], " on channel ", channel, "\n") @tcp_socket.write(Marshal.dump([channel, message])) @tcp_socket.write("\n\n") end def disconnect() # Disconnect this computer from the server # to be implemented end end # The network session can be both a server and a client, or one of the two. # It dispatches communication to registered callbacks determined by the # channel. class NetSession attr_reader :computers def initialize() @messages = Array.new @computers = Array.new @mutex = Mutex.new @receivers = Hash.new end def listen(port) # Start listening for connections on the given port (spawn a thread for # this job) Thread.new(port) do |port| gs = TCPServer.open(port) addr = gs.addr addr.shift puts("Server is on " + addr.join(":")) loop do Thread.start(gs.accept) do |socket| comp = NetComputer.new(socket, self) puts("New computer connecting") # Add to computers array @mutex.synchronize { @computers.push(comp) } print(socket, " is accepted\n") print(@computers.length, " computers connected\n") # Wait for messages until computer disconnects while incoming = socket.gets(nil) message = Marshal.load(incoming) print("Server received ", message, "\n") @mutex.synchronize { @messages.push([message, comp]) } end # Disconnected, close and remove for computers array puts("Computer disconnected") @mutex.synchronize { @computers.delete(comp) } end end end end def connect(host, port) # Start a thread listening for incoming messages Thread.new do # Connect to a server at adress:port print("Connecting to ", host, ":", port, " ...\n") STDOUT.flush socket = TCPSocket.open(host, port) print("Connected from: ", socket.addr.join(":"), "\n") print("Connected to: ", socket.peeraddr.join(":"), "\n") comp = NetComputer.new(socket, self) @computers.push(comp) print("Connected to ", @computers.length, " computers\n") print("Listening to server socket\n") while incoming = socket.gets("\n\n") message = Marshal.load(incoming) print(socket.addr[1], " client received ", message, "\n") @mutex.synchronize { @messages.push([message, comp]) } end # Disconnected puts("Server disconnected") @mutex.synchronize { @computers.delete(comp) } end end def on_receive_call(channel, receiver) @receivers[channel] = receiver end def keep_alive() # Call callback for each received message @mutex.synchronize { @messages.each { |message| channel = message[0][0] mess = message[0][1] from = message[1] if @receivers[channel] @receivers[channel].on_receive(mess, from) end } @messages.clear } end end |