Problem: Große Anzahl von IP-Adressen verwalten!

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
elLobo

Montag 2. Januar 2006, 15:21

Hallo!

Ich möchte gerne in Python eine große Anzahl von IP-Adressen und zugehörigen Port-Nummern verwalten. Ich bekomme Ranges von IP-Adressen und Port-Nummern und will dann aus diesen Tupel bilden. Also <IP:Port> eben. Jedes dieser Tupel darf aber nur einmal benutzt werden.

Irgendwie ist dieses Problem nicht so trivial wie es scheint... die Datenmengen können nämlich sehr groß werden... von den Port-Nummern gibt es ja schon alleine 65 Tausend...

Welche Datenstruktur könnte ich dafür in Python benutzen... ?

Stehe da im Moment voll auf dem Schlauch... über jede Anregung wäre ich dankbar!

mfg elLobo
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 2. Januar 2006, 15:43

Dazu nimmst du am besten ein Set (= Menge), dadurch wird garantiert, dass es jede Tupel nur einmal im Set gibt.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Gast

Montag 2. Januar 2006, 16:11

Leonidas hat geschrieben:Dazu nimmst du am besten ein Set (= Menge), dadurch wird garantiert, dass es jede Tupel nur einmal im Set gibt.
Ahh... Set... kannte ich noch gar nicht... danke!

Aber damit habe ich doch auch das Problem, wenn ich zuviele IPs und Ports habe, die Datenmengen sehr groß werden.... hat jemand Erfahrungswerte, bis zu welcher Größe ich in Python z.B. eine Liste mit Integerwerten füllen kann, bis mir alles abschmiert?

mfg elLobo
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 2. Januar 2006, 16:14

Solange dir das Virtual Memory mitspilet. Auf 32-Bit Systemen hat jeder Prozess 2 GB Speicher zur verfügung, wenn du drüber kommst: schlecht.

Allerdings rate ich dir von Listen ab, nimm dafür eben besser Sets.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 2. Januar 2006, 16:21

Oder gleich direkt eine Datenbank! Vielleicht SQLite...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
elLobo

Montag 2. Januar 2006, 16:33

Leonidas hat geschrieben:Solange dir das Virtual Memory mitspilet. Auf 32-Bit Systemen hat jeder Prozess 2 GB Speicher zur verfügung, wenn du drüber kommst: schlecht.

Allerdings rate ich dir von Listen ab, nimm dafür eben besser Sets.
Worst-Case: Klasse-A-Netz -> 16.774.214 Adressen x 65.536 Port-Nummern = ca. 1 Billion Tupel. :shock:

Je Tupel 8 Byte Speicherbedarf -> ca. 8 Tebibyte :shock:

Selbst ein Klasse-B-Netz würde den Rahmen von 2Gb sprengen...

Habe noch nie so große Datenmengen verwalten müssen...

mfg elLobo
Gast

Montag 2. Januar 2006, 16:34

jens hat geschrieben:Oder gleich direkt eine Datenbank! Vielleicht SQLite...
Hmmm.... werde ich mir anschauen... aber eigentlich wollte ich auf eine Datenbank verzichten... Danke für den Tip!

mfg elLobo
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 2. Januar 2006, 16:36

http://sqlite.org
Supports databases up to 2 terabytes (241 bytes) in size.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 2. Januar 2006, 17:10

elLobo hat geschrieben: Irgendwie ist dieses Problem nicht so trivial wie es scheint... die Datenmengen können nämlich sehr groß werden... von den Port-Nummern gibt es ja schon alleine 65 Tausend...
Welche Datenstruktur könnte ich dafür in Python benutzen... ?
Hi elLobo!

Du könntest "shelve" verwenden. Shelve verhält sich wie ein Dictionary, speichert die Daten aber in ein File-Objekt ab. Das Lesen von einzelnen Werten aus diesem Objekt ist ziemlich schnell. Ich habe das Ganze mit 1 Mio. Datensätze unter Linux ausprobiert.

Hier ein Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import shelve

# Schreiben
sh = shelve.open("filename", protocol = 2)
sh["Vorname"] = "Nudelaug"
sh["Nachname"] = "Thompson"
sh.close()

# Lesen
sh = shelve.open("filename", protocol = 2)
print sh["Vorname"]
print sh["Nachname"]
sh.close()
Beispiel zum Testen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
******************************************************************************
* Description:  Shelve-Test
* Help:         http://www.python.org/doc/current/lib/module-shelve.html
******************************************************************************
"""

import os
import os.path
import shelve

FILENAME = "shelvefile"
MAX = 200000
PROTOCOL = 2


#----------------------------------------------------------------------
def fill_shelve(key = None, value = None):
    """
    Befüllt das Objekt mit Daten.
    """
    
    sh = shelve.open(FILENAME, protocol = PROTOCOL)
    
    print "fill - begin"
    
    if key is None:
        for i in range(MAX):
            sh[str(i)] = "Eintrag Nummer %s" % i
            if i % 1000 == 0:
                print "fill - %s" % i
    else:
        sh[key] = value
        
    sh.close()
    
    print "fill - end"
    

#----------------------------------------------------------------------
def read_shelve(direction = "asc", additional_keys = None):
    """
    Liest ein paar Daten aus dem Shelve aus.
    """
    
    sh = shelve.open(FILENAME, protocol = PROTOCOL)

    print "read - begin"
    
    if direction == "asc":
        for i in range(0, MAX, 1500):
            print "read - %s = %s" % (i, sh[str(i)])
    else:
        for i in range(MAX - 1, 0, -1500):
            print "read - %s = %s" % (i, sh[str(i)])
            
    if additional_keys:
        for key in additional_keys:
            print "read - %s = %s" % (key, sh[key])
    
    sh.close()
    
    print "read - end"
    
    
#----------------------------------------------------------------------
def main():
    """
    Hauptprozedur
    """
    
    if not(os.path.isfile(FILENAME)):
        fill_shelve()

    fill_shelve("Vorname", "Nudelaug")
    fill_shelve("Nachname", "Thompson")
    
    read_shelve("asc")
    read_shelve(
        "desc", 
        (
            "Vorname", 
            "Nachname"
        )
    )


#----------------------------------------------------------------------
if __name__ == "__main__":
    main()
Hier findest du Hilfe zu shelve

mfg
Gerold
:-)

Edit: Protokoll auf das schnellere Binary-Protokoll gesetzt.
Edit2: Um Shelve eine bessere Chance zu geben, habe ich ein Kurzbeispiel eingefügt.
Zuletzt geändert von gerold am Dienstag 3. Januar 2006, 21:51, insgesamt 3-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 2. Januar 2006, 17:13

gerold hat geschrieben:Du könntest "shelve" verwenden.
Dabei würde ich aber das beachten: http://www.python.org/doc/current/lib/node64.html

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Montag 2. Januar 2006, 17:32

jens hat geschrieben:Dabei würde ich aber das beachten: http://www.python.org/doc/current/lib/node64.html
Hi Jens!

Danke, habe ich ins Beispiel eingebaut.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Montag 2. Januar 2006, 20:26

Für so große Datensätze und für so einfachen aufbau würde ich ein Array nehmen. Die Dinger nutzen den Speicher besser, da keine Referenzen und Objekte abgelegt werden, sondern wirklich nur die Werte.

Code: Alles auswählen

>>> from array import array
>>> iplist = []
>>> iplist.append(array("B", [255, 255, 255, 255]))
>>> iplist.append(array("B", [0, 0, 0, 0]))
>>> iplist
[array('B', [255, 255, 255, 255]), array('B', [0, 0, 0, 0])]
TUFKAB – the user formerly known as blackbird
BlackJack

Montag 2. Januar 2006, 21:28

Bei so einer grossen Datenmenge sind auch Arrays nix. Die müssten dann alle in den Speicher passen. Und wenn man das Array dynamisch vergrössert, muss unter Umständen sogar 3x soviel Speicher vorhanden sein, damit das klappt.

elLobo hat noch nicht geschrieben, was er mit den Daten eigentlich machen will. Wenn man zum Beispiel als Anforderung hat, alle Portnummern zu einer gegebenen IP herauszufinden, dann ist das lineare Suchen in Arrays oder Listen von diesen Ausmassen *äusserst* ungünstig.

Ich würde mich dem Vorschlag mit der Datenbank anschliessen. Die sind für solche Datenmengen gedacht.
elLobo

Dienstag 3. Januar 2006, 00:56

BlackJack hat geschrieben: elLobo hat noch nicht geschrieben, was er mit den Daten eigentlich machen will. Wenn man zum Beispiel als Anforderung hat, alle Portnummern zu einer gegebenen IP herauszufinden, dann ist das lineare Suchen in Arrays oder Listen von diesen Ausmassen *äusserst* ungünstig.
I
Es sollen aus einer Liste von gültigen IPs und Ports entsprechende Tupel gebildet werden und diese einem "anderem System" zur Verfügung gestellt werden.

Ich denke man kann an die Sache aus zwei Richtungen ran gehen:

1. Ich bilde aus allen gültigen IPs und Ports ein Tupel und kontrolliere, ob dieses schon benutzt wurde, falls nicht, wird es in eine "Blacklist" eingetragen. Der Vorteil hierbei wäre, dass die Datenmenge recht lansgam steigt, aber mit der Zeit es immer schwieriger wird, ein noch nicht benutztes Tupel zu finden, also steigt auch der Aufwand...

2. Ich erstelle gleich von Beginn an, eine komplette Liste mit allen gültigen Tupeln und lösche dann nach und nach alle benutzten raus. Nachteil, ich brauche verdammt viel Speicherplatz...

Welche Version scheint sinnvoller?

Danke soweit für die Tips... werde mir das alles anschauen...

mfg elLobo
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 3. Januar 2006, 08:28

elLobo hat geschrieben:Es sollen aus einer Liste von gültigen IPs und Ports entsprechende Tupel gebildet werden und diese einem "anderem System" zur Verfügung gestellt werden.
Hi elLobo!

Du schreibst nur, wie du an die Sache ran gehen würdest, aber nicht, wofür du es wirklich brauchst. So können wir dir keinen besseren Vorschlag geben.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten