E.6.6 Paket Net (p_net.py)

# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1997
#
# Dateiname : p_net.py
# Datum : 03.11.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Paket Netz, fasst alle Netzpaket-Klassen
# zusammen
#
# Anmerkungen :
#
# -------------------------------------------------------------
import c_tcp
import c_stopwait1
import c_send
import c_retrieve
 
Klasse c_tcp
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1997
# Dateiname : c_tcp.py
# Datum : 03.11.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Eine einfache TCP Connection Klasse
#
# Anmerkungen :
#
# -------------------------------------------------------------
 
# imports
import socket
import time
 
class c_tcpconn:
         
    #
    # Konstruktor, wird kein Port mit uebergeben
    # dann wollen wir die Verbindung aufbauen(Client)
    #
    def __init__(self,host="",port=0):
        self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     
        if port !=0:
            try:
                self.sock.bind(host,port)
                self.typ="server"
            except socket.error,msg:
                print "---",msg,"---"
                 
        else:
            self.typ="client"
 
 
    #
    # baut eine Verbindung mit host,port auf
    #
    def connect(self,host,port):
        self.sock.connect(host,port)
 
    #
    # wartet auf Verbindungsaufbau
    #
    def accept(self):
        self.sock.listen(5)
        self.peerconn,self.peeraddr = self.sock.accept()
 
    #
    # schreibt buff in den Socket
    #
    def send(self,buff):
        if self.typ=="client":
            self.sock.send(buff)
        else:
            self.peerconn.send(buff)
 
    #
    # wartet auf eine Nachricht die max. buffsize bytes lang ist
    #
    def recv(self,buffsize):
        if self.typ=="client":
            return self.sock.recv(buffsize)
        else:
            return self.peerconn.recv(buffsize)
                     
    #
    # wie recv, wartet aber nur secs Sekunden
    #
    def poll(self,buffsize,secs=1):
        polltime=secs
        erg=""
        if self.typ=="client":
            self.sock.setblocking(0)
        else:
            self.peerconn.setblocking(0)
 
        while erg=="" and polltime>0:
            try:
                if self.typ=="client":
                    erg=self.sock.recv(buffsize)
                else:
                    erg=self.peerconn.recv(buffsize)
            except socket.error:
                erg=""
                time.sleep(1)
                polltime=polltime-1
                     
        if self.typ=="client":
            self.sock.setblocking(1)
        else:
            self.peerconn.setblocking(1)
 
        return erg
 
    #
    # baut eine evtl. bestehende Verbindung ab
    # und schliesst die Sockets
    #
    def close(self):
        if self.typ=="server":
            self.sock.close()
            self.peerconn.shutdown(1)
        else:
            self.sock.shutdown(1)
 
        return
 
 
    #
    # liefert die lokale Adresse zurueck
    #
    def getaddr(self):
        return [socket.gethostname(),self.sock.getsockname()]
 
    #
    #liefert die Remote-Adresse zurueck
    #
    def getpeeraddr(self):
        if self.typ=="client":
            return self.sock.getpeername()
        else:
            return self.peerconn.getpeername()
 
 
 
Klasse c_stopwait1
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1998
# Dateiname : c_stopwait1.py
# Datum : 09.12.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Hier ist eine einfache Stop-Wait Protokoll
# Maschine als Klasse implementiert.
# Anmerkungen : Diese Klasse kann verwendet werden, um
# aus Dokumentemethoden separate Netzverbindung
# zur Datenuebermittlung aufzubauen. Sie ist
# von der Klasse c_tcpconn abgeleitet.
# -------------------------------------------------------------
#
 
# import
from c_tcp import c_tcpconn
import c_bsio
import select
 
class c_stopwait1(c_tcpconn):
    #
    # Konstruktor, initialsiert Variable
    # host,port gibt die Adresse des lokalen sockets an
    # buffsize die Paketgroesse bei der Uebertragung
    # timeout die Zeit (in Sekunden) die auf eine Bestaetigung
    # gewartet wird, mittels debug=1 werden zusaetzliche
    # Nachrichten ueber den Verlauf der uebertragung ausgegeben
    #
    def __init__(self,host="localhost",port=0,buffsize=512,timeout=5,debug=0):
        # Konstruktor der Basisklasse aufrufen
        c_tcpconn.__init__(self,host,port)
        self.blocksize=buffsize
        self.timeout=timeout
        self.debug=debug
    #
    # Destruktor, trennt die Verbidung falls sie aufgebaut ist
    #
    def __del__(self):
        try:
            c_tcpconn.sock.close()
            c_tcpconn.peerconn.close()
        except:
            pass
    #
    # fuehrt einen TCP connect an die durch
    # host,port gegebene Adresse aus
    #
    def connect(self,host,port):
        c_tcpconn.connect(self,host,port)
    #
    # wartet auf Verbidungsaufnahme durch eine Gegenstelle
    #
    def accept(self):
        c_tcpconn.accept(self)
         
    #
    # sendet sendstr mittels des Stop-Wait Protokolls
    # dabei wird die Nachricht segmentiert (blocksize)
    # und die Uebertragung eines Pakets bei Uebertragunsfehlern
    # bis zu 10 mal wiederholt
    #
    def send_str(self,sendstr):
        hilf=sendstr
        errcount=0
        muell=self.poll(self.blocksize+1,1)
         
        while len(hilf)>0 and errcount < 10:
            self.send(hilf[:self.blocksize])
 
            if self.debug:
                print "send:",hilf[:self.blocksize],len(hilf[:self.blocksize])
 
            ack=self.poll(8,self.timeout)
 
            if self.debug:
                print "recv:",ack
 
            if ack=="ACK"+str(len(hilf[:self.blocksize])):
                hilf=hilf[self.blocksize:]
            else:
                errcount=errcount+1
 
        # Konnten wir alles uebertragen
        if errcount<10:
            ackend=0
            while ackend==0 and errcount <10:
                self.send("END")
                ack=self.poll(8,self.timeout)
 
                if self.debug:
                    print "recv:",ack
 
                if ack=="ACK3":
                    ackend=1
                else:
                    errcount=errcount+1
        # Rueckgabewert ermitteln
        if errcount < 10:
            return 0
        else:
            return -1
         
    #
    # wie send_str, nur wird die Datei fname gesendet
    #
    def send_file(self,fname):
        fd=c_bsio.c_bsio(fname,"r")
        errcount=0
        buff=" "
        fd.open()
        while buff!="" and errcount < 10:
            buff=fd.read(self.blocksize)
            self.send(self,buff)
            ack=self.poll(8,self.timeout)
            if self.debug:
                print "recv:",ack
            if ack!="ACK"+str(len(buff)):
                fd.seek(-len(buff),0)
                errcount=errcount+1
        # Konnten wir alles uebertragen
        if errcount<10:
            ackend=0
            while ackend==0 and errcount <10:
                self.send(self,"END")
                ack=self.poll(8,self.timeout)
                if self.debug:
                    print "recv:",ack
                if ack=="ACK3":
                    ackend=1
                else:
                    errcount=errcount+1
        fd.close()
        # Rueckgabewert ermitteln
        if errcount < 10:
            return 0
        else:
            return -1
         
             
    #
    # empfaengt eine Zeichenkette von der Gegenstelle
    #
    def recv_str(self):
        erg=""
        buff=""
        if self.typ=="server":
            select.select([self.peerconn.fileno()],[],[])
        else:
            select.select([self.sock.fileno()],[],[])
 
        while buff !="END":
            buff=self.poll(self.blocksize,self.timeout)
 
            if self.debug:
                print "recv:",buff
 
            if buff !="":
                if buff !="END":
                    erg=erg+buff
                self.send("ACK"+str(len(buff)))
 
                if self.debug:
                    print "send:ACK"+str(len(buff))
 
            else:
                self.send("ERR")
 
                if self.debug:
                    print "send:ERR"
 
        return erg
    #
    # schreibt alle empfangenen Daten in die Datei mit
    # dem Namen fname
    #
    def recv_file(self,fname):
        fd=c_bsio.c_bsio(fname,"a+")
        fd.open()
        buff=""
        while buff !="END":
            buff=self.poll(self.blocksize,self.timeout)
            if self.debug:
                print "recv:",buff
            if buff !="":
                if buff !="END":
                    fd.write(buff)
                self.send("ACK"+str(len(buff)))
                if self.debug:
                    print "send:ACK",str(len(buff))
            else:
                self.send("ERR")
                if self.debug:
                    print "send:ERR"
            fd.close()
            return 0
 
 
Klasse c_send
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1998
# Dateiname : c_send.py
# Datum : 09.12.1997
# letzte Änderung :
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Diese Klasse versendet Teile eines bestimmten
# Dokuments ueber ein separate Netzverbindung
# Anmerkungen : Diese Klasse wird von den Klassen c_sgmlquery
# und c_stopwait1 abgeleitet.
#
# -------------------------------------------------------------
#
class c_send(c_sgmlquery,c_stopwait1):
    #
    # Konstruktor
    # ident gibt die Dokument-ID an
    # peerhost, peeport geben die Netzadresse des Peers an
    # an diese Adresse werden alle Daten gesendet
    # blocksize gibt die Paketgroese an (s. c_stopwait1)
    # timeout gibt den timeout fuer das Warten auf Paket-
    # bestaetigungen an.
    #
    def __init__(self,ident,peerhost,peerport,blocksize,timeout):
        # Konstruktoren der Basisklassen aufrufen
        c_sgmlquery.__init__(self,ident)
        c_stopwait1.__init__("",0,blocksize,timeout)
        self.peerport=peerport
        self.peerhost=peerhost
        self.connect(self.peerhost,self.peerport)
        self.ident=ident
    #
    # Destruktor
    #
    def __del__(self):
        # Destruktor der stopwait Klasse aufrufen
        c_stopwait1.__del__()
    #
    # sendet als Bitstrom gespeicherte Daten
    # und zwar von der Position start bis Position end
    # wobei start und end absolute Positionen innerhalb
    # des Bitstroms bezeichnen
    #
    def send_bs(self,start,end):
        import c_bsio
        from sc_globals import *
        fname=DL_BSOUTPATH+str(ident)+'.bs'
        fd=c_bsio.c_bsio(fname,'r')
        fd.seek(start)
        while fd.tell()<=end:
            buff=fd.readline()
            self.send_str(buff)
 
        fd.close()
        del fd
    #
    # sendet den Inhalt des tagcounten Tags mit Namen
    # tagname an den Peer
    #
    def send_tagcontents(self,tagname,tagcount):
        self.send_str(self.sgmlquery_tagcontens(tagname,tagcount))
        return 0
    #
    # sendet den das tagcounte Tag mit Namen
    # tagname an den Peer
    #
    def send_tag(self,tagname,tagcount):
        self.send_str(self.sgmlquery_tag(tagname,tagcount))
        return 0
    #
    # sendet die Tag-Struktur (Strukturbaum) des Dokuments
    # an den Peer
    #
    def send_structure(self):
        self.send_str( self.sgmlquery_structure())
        return 0
    #
    # sendet das gesamte Dokument an den Peer
    #
    def send_doc(self):
        self.send_str(self.sgmlquery_doc())
        return 0