Informationen über IP -Adressen..

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
pysq
User
Beiträge: 31
Registriert: Samstag 29. November 2008, 17:48

Hallo,

ich programmiere ein Netzwerkspiel (Server, Client).
Gibt es eine Möglichkeit bei Python unter Windows via Broadcast o.ä. eine Liste mit verfügbaren Server in einem lokalen Netzwerk (z. B. 192.168.0.x) zu erstellen?

Ich glaube es ist dazu notwendig zunächst erst einmal notwendig, mit Python die eigene IP-Adresse herauszufinden.

mfg pysq
Benutzeravatar
limepix
User
Beiträge: 37
Registriert: Dienstag 11. November 2008, 16:54

Hi pysg!

vor einem ähnlichem problem bin ich selber auch gesessen...
ich wollte einfach ein paar nachrichten durch ein netzsegment schicken und jeder der einen "empfänger" offen hatte hat diese dann empfangen...

ich denke, was du dir mal anschauen solltest ist die seite

http://pyro.sourceforge.net/

nach ca ner halben std einlesen in die doku, hats dann auf anhieb geklappt...

ich hoffe ich konnte dir weiter helfen!


EDIT:Ach ja, was ich vergessen habe - mit pyro musst du dich nicht um IP Adressen kümmern... dieser "namensdienst" bedient sich eines bereits fertig eingebautem broadcast mechanismus.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Nach Q3A-Servern kann man so scannen: Arena Lurker. Je nach Spiel sehen die Ports, Anfragen und Antworten unterschiedlich aus.

Du kannst dich an bestehenden Protokollen orientieren und den Server deines Spiels einfach auf einem UDP-Port nach Broadcasts lauschen lassen.

PyRo ist meiner Ansicht nach nicht so geeignet.

Du kannst dir RakNet ansehen und schauen, ob du mit den Lizenzbedingungen und den Python-Bindings (IIRC "pyraknet") klar kommst.
Benutzeravatar
pysq
User
Beiträge: 31
Registriert: Samstag 29. November 2008, 17:48

@ limepix:
beim Ausführen der Setup (Pyro-3.8.1.win32.exe) kommt etwa folgender Fehler:
Anwendung konnte nicht gestartet werde [...] Side-by-Side Konfiguration ungültig.

@YOGi:
das Prinzip wie nach den Q3A Servern gesucht könnte zu meinem Code passen. Ich hab erstmal pygtk installiert.
Allerdings erhalte ich bei import gtk einen importerror von gobject??

mfg pysq
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

pysq hat geschrieben:Allerdings erhalte ich bei import gtk einen importerror von gobject??
Dann brauchst du PyGObject.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Du kannst auch das GTK-Geraffel rauswerfen (das zeigt und aktualisiert und ein Dock-Icon) und stattdessen ein paar `print`-Statements einwerfen.

Das hier reicht:

Code: Alles auswählen

if __name__ == '__main__':
    with Scanner() as scanner:
        print list(scanner.scan())
Den GTK-Teil sowie `MainLoop` und die GTK-Imports können dann raus.
Benutzeravatar
pysq
User
Beiträge: 31
Registriert: Samstag 29. November 2008, 17:48

alles klar : ) ich habe gtk einfach erst einmal rausgeschmissen.
ich hab das ganze jetzt erst einmal mit einem einfachen UDP Server ausprobiert, aber

Code: Alles auswählen

self.socket.sendto(request, ('<broadcast>', port))
stellt mit einem Server nur eine sehr kurze Verbindung her, die praktisch sofort wieder zurückgesetzt wird. Der Server hat keine Zeit, über denselben socket wieder zu antworten. Wie kann ich realisieren, dass der Server antwortet?
Gibt es auch eine Möglichkeit, das ganze mit TCP Servern zu gestalten?.. wenn ja, dann wahrscheinlich wohl nur umständlich..

Hier ist nochmal der Code für den Scanner

Code: Alles auswählen

import socket

class Scanner(object):

    def __init__(self, timeout=2):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.socket.settimeout(timeout)
        self.socket.bind(('', 0))
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.socket.close()

    def scan(self, port=50000):
        request = 'Nachricht'
        self.socket.sendto(request, ('<broadcast>', port))
        while True:
            try:
                data, addr = self.socket.recvfrom(1024)
                print data, addr
                yield data
            except socket.timeout:
                break

if __name__ == '__main__':
    s=Scanner()
    
    while True:
        print '* Scanning ...', i
        try:
            a=list(s.scan())
            print a
        except KeyboardInterrupt:
            print 'Ctrl-C pressed, aborting.'
            break
udp server

Code: Alles auswählen

import socket, time
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

try: 
    s.bind(("", 50000)) 
    while True: 
        daten, addr = s.recvfrom(1024)
        print daten, addr
        s.sendto('test',(addr[0], 50001))
        time.sleep(0.01)
finally:
        s.close()
mfg pysq
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

hallo!

hier nur mal ein ausschnitt aus einem programm, das ich geschrieben habe. es duerfte dir weiterhelfen.

hier ist der client:

Code: Alles auswählen

import select, socket

def search_computers(waittime=3, port=55099):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    try:
        s.sendto("PING", ("<broadcast>", port))
    except socket.error:
        return []

    clients = []
    while True:
        if select.select([s], [], [], waittime)[0]:
            data, addr = s.recvfrom(13)
            if data == "PONG" and not addr[0] in clients:
                try:
                    name = socket.gethostbyaddr(addr[0])[0] + " (" + addr[0] + ")"
                except socket.error:
                    name = addr[0]
                clients.append(name)
        else:
            break
    return clients
und hier der responder:

Code: Alles auswählen

import select, socket, threading

def start_ping_responder(port=55099):
    thrd = ResponderThread(port)
    thrd.setDaemon(1)
    thrd.start()

class ResponderThread(threading.Thread):
    def __init__(self, port):
        threading.Thread.__init__(self)
        self.port = port

    def run(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.bind(("", self.port))
        except socket.error, why:
            print "error: %s" % why
            return
        while True:
            if select.select([s], [], [])[0]:
                data, addr = s.recvfrom(11)
                if data == "PING":
                    s.sendto("PONG", addr)
wenn du das ein wenig an deine beduerfnisse anpasst, dann duerfte es kein problem mehr sein die rechner zu finden.

lg
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
Benutzeravatar
pysq
User
Beiträge: 31
Registriert: Samstag 29. November 2008, 17:48

danke, das tut es!
Benutzeravatar
pysq
User
Beiträge: 31
Registriert: Samstag 29. November 2008, 17:48

und noch einmal einen Nachtrag, eigene IP herausfinden:

Code: Alles auswählen

name = socket.gethostname()
ip = socket.gethostbyname(name)
Antworten