socketverwaltung

Code-Stücke können hier veröffentlicht werden.
Antworten
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Montag 16. Oktober 2006, 11:45

hi!
ich habe in zwei skripten eine "socketverwaltung" geschrieben, und dachte mir, dass sich da soviel wiederholt, dass ich ein codesnippet mache. ob ihr es brauchen könnt, ka, aber ich :-)

Code: Alles auswählen

#networker.py
#stdlib
import socket
import time
import sys

#own lib
import firewall

class MainSocket:
    __doc__ = """this the mainsocket where you can read and write to"""

    def __init__(self, mainport):
        self.closed = False
        recvport = mainport  + 1
        self.sendport = mainport
        self.sendsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      
        self.recvsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
        self.recvsocket.settimeout(5)
        self.recvsocket.bind(('localhost', recvport))
        self.my_firewall = firewall.FireWall()

    def search(self, seconds):
        endtime = time.time() + seconds
        self.recvsocket.settimeout(1)
        addrs = list()
        verifications = list()
        while endtime > time.time(): 
            try:
                self.recvsocket.listen(1)
                conn, (addr, strange_number) = self.recvsocket.accept()
                addrs.append(addr)
                verification = conn.recv(1024)
                verifications.append(verification)
                print "%s tried to connect using %s" % (addr, verification)
            except socket.timeout:
                pass 
        for addr in addrs:
            if addr in self.my_firewall.get_addrs():
                continue
        self.recvsocket.settimeout(5)
        print (addrs, verifications)
        return (addrs, verifications)


#    def read(self, bufsize=1024):
 #       __doc__ = "'reads' from the socket. recieves data from the recvsocket"
  #      self.recvsocket.listen(5)
   #     conn, addr = self.recvsocket.accept()
    #    if addr in self.my_firewall.get_addrs():
     #       return None
      #  return conn.recv(bufsize)

    def write(self, data, address):
        __doc__ = """'writes' data to the socket. 
        sends the data to the given address.
        the connection i use must be got by search()!"""
        self.sendsocket.connect((address, self.sendport))
        self.sendsocket.send(data)
        self.sendsocket.close()

    def close(self):  
        self.sendsocket.close()
        self.recvsocket.close()
        self.closed = True

    def __del__(self):
        if not self.closed:
            self.close()


class SocketPair:
    __doc__ = """this is a socketpair where you can read and write to"""

    def __init__(self, ip_address, sendport, recvport, is_server):
        self.closed = False
        self.sendsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      
        tmp_recvsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        if is_server: 
            print "creating the reciever..."
            tmp_recvsocket.bind(('localhost', recvport))
            tmp_recvsocket.listen(1)
            self.recvsocket, addr = tmp_recvsocket.accept()
            print "creating the sender..."
            for i in range(20):
                try:
                    self.sendsocket.connect((ip_address, sendport))
                except socket.error:
                    continue
                time.sleep(1)
        else:
            print "creating the sender..."
            self.sendsocket.connect((ip_address, sendport))
            print "creating the reciever..."
            tmp_recvsocket.bind(('localhost', recvport))
            tmp_recvsocket.listen(1)
            self.recvsocket, addr = tmp_recvsocket.accept()


        tmp_recvsocket.close()


    def read(self, bufsize=1024):
        __doc__ = "'reads' from the socket. recieves data from the recvsocket"
        return self.recvsocket.recv(bufsize)

    def write(self, data):
        __doc__ = """'writes' data to the socket. 
        sends the data to the given address"""
        self.sendsocket.sendall(data)

    def close(self):  
        self.sendsocket.close()
        self.recvsocket.close()
        self.closed = True

    def __del__(self):
        if not self.closed:
            self.close()
        


class ServerSockets:
    __doc__ = """this contents all the sockets of the gamers. 
    the mainport is the startpoint of naming the sockets.
    so if the mainsocket is 21000, the first socketpair will be 21001
    and 21002, the second 21003 and 21004 and so on."""

    def __init__(self, mainport):
        self.maincon = MainSocket(mainport)
        self.sockets = dict()
        self.ports = [mainport, mainport+1]

    def search(self, seconds):
        packets = self.maincon.search(seconds)
        addrs, verifications = packets
        for packet in zip(addrs, verifications):
            print 'a packet looks like ', packet
            addr, verification = packet
            print "%s tried to connect to localhost using '%s'" % (addr, 
                                                                 verification)
        return packets

    def create(self, name, ip_address):
        __doc__ = "creates a socket from some standard-parametres"
        sendport = self.ports[-1] + 1
        self.ports.append(sendport)
        recvport = sendport + 1
        print "i send to %i and recieve on %i" % (sendport, recvport)
        self.ports.append(recvport)
        print "values...", str(sendport), ip_address
        self.maincon.write(str(sendport), ip_address)
        print "client recieved its port..."
        self.sockets[name] = SocketPair(ip_address, sendport, recvport, True)
        print "the socket for the server is made..."
        print "the client '%s' is created!" % (name, )
        return self.sockets[name]

    def connection(self, name):
        __doc__ = """
        returns the real connection which can be used to talk to a client"""
        return self.sockets[name]

    def close(self, name):
        __doc__ = "closes one socket where the owner has the name 'name'"
        self.sockets[name].close()
        del self.sockets[name]

    def close_all(self):
        __doc__ = "closes all sockets"
        for _socket in self.sockets.values():
            _socket.close()



#now this is for the client
def initiate_connection(host, mainport, verification):
    sendport = mainport + 1
    recvport = mainport
    print "i send to %i and recieve on %i" % (sendport, recvport)
    sendsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)      
    tmp_recvsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
    tmp_recvsocket.bind(('localhost', recvport))
    print "now connecting to the host..."
    sendsocket.connect((host, sendport))
    sendsocket.send(verification)
    tmp_recvsocket.listen(1)
    recvsocket, addr = tmp_recvsocket.accept()
    answer = recvsocket.recv(1024)
    print answer
    new_port = int(answer)
    print "the new recv-port is %i, so the sendport is %i" % (new_port, new_port+1)
    tmp_recvsocket.close()
    recvsocket.close()
    return new_port


def connect(host, port, verification):
    __doc__ = "the client which can access on this system"
    recvport = initiate_connection(host, port, verification)
    sendport = recvport + 1
    print "i send to %i and recieve on %i" % (sendport, recvport)
    return SocketPair(host, sendport, recvport, False)
der firewall ist noch nicht ganz fertig ;-)

Code: Alles auswählen

#firewall
#a little 'firewall' saving unallowed ip-addresses.
#there is a log-file where every attack is written.
#if it is 24:00:00 or later, the file will be removed.

import os, time

class FireWall:

    def __init__(self):
        return None
        if not os.path.exists('logfile.log'):
            self.log_file = file('logfile.log', 'w+')
        last_mod = os.path.getmtime('logfile.log')
        mod_day = time.strftime('%j', time.gmtime(last_mod))
        mod_year = time.strftime('%Y', time.gmtime(last_mod))
        actual_day = time.strftime('%j')
        actual_year = time.time.strftime('%Y')
        if mod_year < actual_year or mod_day < actual_day:
            os.remove('logfile.log')  
        self.log_file = file('logfile.log', 'w+')

    def add_addr(self, addr):
        #self.log_file.write('%s\n' % addr)
        pass

    def get_addrs(self):
        #return self.log_file.readlines()
        return []

    def shutdown(self):
        pass
        #self.log_file.close()
den firewall werde ich dann mal irgendwann hier aktualisieren, die prints aus dem networker auch entfernen, war noch grade beim debuggen
http://www.cs.unm.edu/~dlchao/flake/doom/
BlackJack

Montag 16. Oktober 2006, 13:56

Docstrings sind einfache Zeichenketten die als erstes in Klassen- und Funktionsdefinitionen stehen. Das Du sie explizit an `__doc__` bindest ist unnötig bzw. bei Funktionen sogar falsch, weil Du damit einfach einen lokalen Namen definierst, der "aussen" gar nicht sichtbar ist.

Und was das gebrauchen angeht, ich habe mal kurz drübergeschaut und echt keine Ahnung was der Code macht und wie man ihn benutzen sollte.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Montag 16. Oktober 2006, 14:54

das mit den doc-strings wusste ich gar nicht, vielen dank!
tschuldigung, dass ich die erkärung der benutzung nicht mitgeschickt habe:
der sinn dahinter ist, dass ich tcp auf localhost laufen lassen will.
nun dachte ich mir, dass es schneller wäre, einen port zum senden und einen zum empfangen zu nehmen. die alternative wäre ja, den gleichen port mehrfach zu öffnen und zu schließen.
wenn das gesammt sich nur zwischen zwei unterschiedlichen rechnern läuft, ist das ganze kein Problem. aber wenn zwei sender und zwei empfänger sich einen port teilen müssen, geht das nicht. woher soll schließlich gewusst sein, welcher empfänger nun empfangen darf...
das gesammte ist so darauf ausgelegt, dass man sich auch nicht darum kümmern muss, welche ports gerade genutzt werden, um sich mit einem client zu unterhalten. das wird ebenfalls darin behandelt...

Code: Alles auswählen

#!/usr/bin/python
#server.py
import networker as nt
print "creating server..."
server = nt.ServerSockets(21016)
print "searching..."
addrs, verifications = server.search(6)
print addrs, verifications
for addr, verification in zip(addrs, verifications):
    conn = server.create(verification, addr)
    conn.write('hallo')
    print conn.read()
server.close_all()

Code: Alles auswählen

#!/usr/bin/python
#client.py
import networker as nt
conn = nt.connect('localhost', 21016, 'test')
print conn.read()
conn.write('hallo')
conn.close()
das ist jetzt ein simpler datenaustausch von einem 'hallo'
http://www.cs.unm.edu/~dlchao/flake/doom/
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Montag 16. Oktober 2006, 16:28

Ports zweimal öffnen? Je einen Port zum Senden und Empfangen? Mir scheint, du hast da bzgl. Sockets einige Dinge noch nicht ganz... verinnerlicht ;)
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Montag 16. Oktober 2006, 16:33

tschuldigung, dass ich so frage, aber wie würdest du das denn lösen?
ich will ganz gerne, dass das auch über localhost laufen kann,
und hatte probleme dabei, zwei empfänger am gleichen port lauschen zu lassen...
http://www.cs.unm.edu/~dlchao/flake/doom/
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Montag 16. Oktober 2006, 18:51

Was genau hast du nochmal vor?
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Dienstag 17. Oktober 2006, 20:14

ich will eine zwei-wege kommunikation:
client loggt sich beim server auf einem festen port ein,
nun soll eine kommunikation zwischen dem client und dem server entstehen.
diese soll eine zwei-wege-kommunikation sein,
client schickt was zum server, server was zum client.
server soll wissen, welcher client das ist,
das soll (einigermaßen) sicher sein
(eigene verbindung, kein verifizierungsstring bei jedem post notwendig)
daher wird das ganze an einen neuen port gebunden.
nun soll das ganze auch auf localhost gehen.
da bekommt der server beim einloggen eine meldung (wegen accept() und einem post mit einem verifizierungsstring an diese adresse),
nun muss der client warten und empfangen, wenn der server wieder antwortet.
der sucht aber für eine dem client unbekannte zeit und blockiert so den socket zum empfangen. nun muss aber der client den kontakt mit dem server wieder aufnehmen, muss empfangen, auf welchem port die private kommunikation stattfindet. wie soll man das verwirklichen ohne zwei sockets zu benutzen. einen, auf dem der server empfängt, einen, auf dem der client wartet und auf rückmeldung hofft.
ich habe zwar noch nicht versucht, bei der privaten server-client-kommunikation zwei programmen das empfangen der daten eines sockets zu erlauben, dachte mir aber, dass das nicht gehen wird.
woher soll man wissen, ob das die botschaft an den client oder an den server war?
http://www.cs.unm.edu/~dlchao/flake/doom/
BlackJack

Dienstag 17. Oktober 2006, 20:26

Ich bin verwirrt. Und zwar extrem. Du machst da sehr komische Sachen.

Server haben für gewöhnlich einen festen Port, damit man sie findet. Ein Client verbindet sich zu diesem Port. Dabei bekommt der Server einen neuen Port von `accept()` über den die Kommunikation dann abgewickelt wird. Über diese Verbindung kann man in beide Richtungen kommunizieren. Man braucht also nur eine Verbindung. Alle Ports bis auf den einen festen Serverport lässt man sich vom Betriebssystem zuweisen. Welche halt gerade frei sind.

Da ist es völlig egal ob Server und Client auf unterschiedlichen Rechnern, oder beide auf 'localhost' laufen.
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Dienstag 17. Oktober 2006, 20:48

da war der haken:
ich dachte, dass beim accept() der alte port weiterbenutz werden würde.
dann ist der code ja wirklich sinnlos :-D :-D :-D
http://www.cs.unm.edu/~dlchao/flake/doom/
skypa
User
Beiträge: 97
Registriert: Freitag 5. Januar 2007, 03:13

Montag 29. Januar 2007, 21:05

hehe geil, den Thread muss ich mir merken, sehr unterhaltsam und aber auch lehrreich!
Antworten