Communicating with multiple computers on the same network through Maya

So I’m looking into a tool that I have an idea for.

I want to communicate from computer A’s Maya instance on my network to computer B’s Maya instance on my network. I don’t want to send scenes or anything, but rather a tiny stream of information.

I’m curious as to how I would start researching this and things that I can use. I’d prefer to use Python, but if I have to use a method utilizing C++ instead, that would be fine.
Thanks.

You want a peer-to-peer ad hoc network in python. There are a few examples of this out there you can borrow from. And you might want to look at twisted or another framework, but those bring along a lot of overhead.

You might also want to look into the world on Remote Procedure Calls in Python. RPC is a superset of messaging over Python-P2P systems that not only passes messages, but those messages say, “Run this code for me.” In your case, the code you want executed might just be sendAMessage(myMessage) or logAnError(myError). You define what those functions mean.

This is all vanilla Python. I would probably write the communications layer as it’s own module, and then wrap that in a Maya specific module. This way you can reuse the same code in any Python application. On the Maya side, you’re going to have to look into multithreading and Maya’s special needs when dealing with multithreading.

Good Luck Mr. Bond

EDIT: Oh yeah, one of the things you’re going to have to think about is “how do your peers find each other?” The easiest way to do this if you own all the machines in question is to post a list of the peers you want to be able to talk to each other along with the code. If you want this to happen automatically, the term for this is auto-discovery, and that rabbit hole is pretty deep unless you find a library that does it for you. You can also set it up so that one machine is the central server and that machine communicates with all the other machines and optionally provides look-up services between them if you want it truly peer-to-peer.

For example, you want two artists to be able to chat with each other from within Maya. Each Maya session would register itself with the central server, and when one of them sends a message to the other, it either gets sent through the server, or it asks the server for the other’s IP address.

[QUOTE=btribble;27663]You want a peer-to-peer ad hoc network in…[/QUOTE] AWESOME. Thank you so much, I’m sure this will help out a ton. I’ll start looking through it after work today!

Or you can just use the commandport to send Mel or python code directly to Maya via the lab.

Might be useful if you’re doing this on windows


import socket
import subprocess
from Queue import Queue
from threading import Thread

"""
module lan

this namespace is for utility functions deailing with simple questions about the
local network. It's not for serious networking code - just for inspecting the
LAN (eg, looking to see what other machines are around

"""


def _ip_format(item):
    """
    Convert an ip string into a tuple (N.N.N.N)
    """
    return tuple(map(int, item.split(".")))


def _ip_to_str(ip):
    """
    Converts an ip tuple (N.N.N.N) to a string
    """
    if hasattr(ip, '__iter__'):
        return (".".join(map(str, ip)))
    else:
        return ip


def ip_info():
    """
    Returns a dictionary with the hostname, ip address, and subnet mask of the local machine
    
    Note this uses the windows ipconfig command, and it will return the first
    set of info it finds -- if there are multiple adapters it will return the
    first one it sees
    
    If the command can't be parsed, raises a RuntimeError
    """
    po = subprocess.Popen("ipconfig", stdout=subprocess.PIPE)
    subnet, ip, gateway = None, None, None
    retcode = po.communicate()
    for eachLine in retcode[0].splitlines():
        if eachLine:
            if eachLine.count("Subnet Mask"):
                subnet = _ip_format(eachLine.partition(":")[-1].strip())
            if eachLine.count('IPv4 Address'):
                ip = _ip_format(eachLine.partition(":")[-1].strip())
            if eachLine.count('Default Gateway'):
                gateway = _ip_format(eachLine.partition(":")[-1].strip())

        if subnet and ip and gateway:
            return {
                "subnet": subnet,
                "ip": ip,
                "gateway": gateway
            }

    raise RuntimeError, "unable to determine IP info"


def ping(ip):
    """
    Pings the supplied ip ( a string or a tuple). Returns -1 if the hose cannot be found and 1 if it can.
    
    @todo: parse out the actual ping time
    """
    po = subprocess.Popen("ping -n 1 " + _ip_to_str(ip), stdout=subprocess.PIPE)
    result = po.communicate()[0]
    if result.count("unreachable"):
        return -1
    else:
        return 1


def scan_local_network(threads=4):
    """
    Scans the local network and returns a list of all visible machines. This
    process takes several seconds of real time. User can supply an number of
    threads to use in the scan, which speeds up the query ( default nubmer of
    threads is 4)
    
    The entries in the result are in the same format as socket.gethostbyaddr
    """
    ip_queue = Queue()
    results = []
    subnet = ip_info()['ip']
    for suffix in range(0, 255):
        newIp = subnet[0], subnet[1], subnet[2], suffix
        ip_queue.put(newIp)

    # inner proc
    def _test_ip(in_q, out_q):
        while in_q.not_empty:
            ip = _ip_to_str(in_q.get())

            p = ping(ip)
            if p > -1:
                try:
                    machine = socket.gethostbyaddr(_ip_to_str(ip))
                    out_q.append(machine)
                except:
                    pass
            in_q.task_done()

    # spin up as many threads as requested. Numbers > 4 don't help too much
    for i in range(threads):
        worker = Thread(target=_test_ip, args=(ip_queue, results))
        worker.setDaemon(True)
        worker.start()

    # block until scan is complete
    ip_queue.join()
    return results


__all__ = ['ping', 'scan_local_network', 'ip_info']

Thanks, Steve!

I’m not sure if that would work(just because I’ve never done it) but I’ll definitely look into it as an option. Thanks!