(Verständnis)problem mit Threads (in Verbindung mit sockets)

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.
Antworten
d@tenmaulwurf
User
Beiträge: 7
Registriert: Dienstag 2. Mai 2006, 11:27

Hallo!

Ich möchte mir einen kleinen Proxy bauen und möchte nun, dass pro Array-Element (redirevts) auf einem bestimmten Port gelauscht wird.
Letzendlich soll der Codeblock nur auf den Ports '44391' und '99391' lauschen.

Das Problem hierbei ist, dass das threading nicht so funktioniert wie ich mir das vorstelle.
Er kommt - auch ohne den 'thread.start_new_thread'-Teil - nicht in den 2. Durchgang der Schleife.

Er lauscht - scheinbar nicht in einem Thread - auf Port 44391 und kommt nicht weiter.

Code: Alles auswählen

$ python test.py 
host1, 44391
Habe ich das mit dem Threading falsch verstanden und zu sowas kann man es nicht nutzen?

Wenn doch - wie?

Vielen Dank schonmal im voraus,

hoffe ihr hattet frohe Ostern :)

d@tenmaulwurf


Code: Alles auswählen

import socket
import thread

redirects = [(44391,'host1',443), (99391,'host2',993)];
server = [];

def listener (redirect):
	server.append (socket.socket ( socket.AF_INET, socket.SOCK_STREAM ));
	server[i].bind ( ( '127.0.0.1', redirect[0] ) );
	server[i].listen ( 1 );
	server[i].accept ();

i = 0;
for redirect in redirects:
	print redirects[i][1] + ', ' + str (redirects[i][0]);
	thread.start_new_thread (listener (redirects[i]))
	i = i+1;
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Zeile 17 muss heissen:

Code: Alles auswählen

thread.start_new_thread (listener, redirects[i])
Sonst rufst du start_new_thread mit den Rueckgabewert des Funktionsaufrufs auf. Etwas komfortabler ist das threading-Modul.

Auf den Laufindex i kannst du uebrigens verzichten.
d@tenmaulwurf
User
Beiträge: 7
Registriert: Dienstag 2. Mai 2006, 11:27

Rebecca hat geschrieben:Zeile 17 muss heissen:

Code: Alles auswählen

thread.start_new_thread (listener, redirects[i])
Sonst rufst du start_new_thread mit den Rueckgabewert des Funktionsaufrufs auf. Etwas komfortabler ist das threading-Modul.

Auf den Laufindex i kannst du uebrigens verzichten.
Vielen Dank für deine schnelle Antwort, jedoch bekomme ich im zweiten Durchgang dann folgende Exception an den Kopf geworfen:

Code: Alles auswählen

$ python test.py 
host1, 44391
Unhandled exception in thread started by <function listener at 0x64530>
TypeError: listener() takes exactly 1 argument (3 given)
host2, 99391
Unhandled exception in thread started by 
Error in sys.excepthook:

Original exception was:
Wieso werden der Funktion listener beim zweiten Durchlauf auf einmal 3 Argumente übergeben ?!?
Zuletzt geändert von d@tenmaulwurf am Dienstag 10. April 2007, 13:15, insgesamt 1-mal geändert.
BlackJack

Auf die Semikola an den Zeilenenden auch.

Wobei das mit dem Index `i` so wie es jetzt da steht eine sehr fragile Angelegenheit ist, insbesondere die Verwendung des globalen `i` in der `listener()`-Funktion. Das ist sehr hässlich und nicht thread-safe.
d@tenmaulwurf
User
Beiträge: 7
Registriert: Dienstag 2. Mai 2006, 11:27

BlackJack hat geschrieben:Auf die Semikola an den Zeilenenden auch.

Wobei das mit dem Index `i` so wie es jetzt da steht eine sehr fragile Angelegenheit ist, insbesondere die Verwendung des globalen `i` in der `listener()`-Funktion. Das ist sehr hässlich und nicht thread-safe.
Das mit dem Simikola weiß ich, weiß ich aus Erfahrung, dass ich sie in anderen Sprachen dann immer vergesse. Deshalb hab ich mir angewöhnt an jedes Zeilenende ein solches zu setzen.

Was meinst du mit "nicht thread-safe"? Wie würdest du das machen?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

@d@tenmaulwurf: Nicht nur das mit dem Semilokon ist untypisch. Auch die vielen Leerzeichen macht man i.d.R. nicht. Allgemein zum Codestyle, schau mal hier: http://www.python-forum.de/topic-9741.html

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
d@tenmaulwurf
User
Beiträge: 7
Registriert: Dienstag 2. Mai 2006, 11:27

Na toll:

Python 2.3.5 (#1, Mar 20 2005, 20:38:20)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1809)] on darwin

$ python test.py
host1, 44391
Unhandled exception in thread started by <function listener at 0x64530>
Traceback (most recent call last):
File "test.py", line 12, in listener
server.bind ( ( '127.0.0.1', redirect[0] ) );
IndexError: list index out of range
host2, 99391
Unhandled exception in thread started by
Error in sys.excepthook:

Original exception was:
$






Python 2.4.4 (#2, Jan 13 2007, 17:50:26)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2

$ python test.py
host1, 44391
host2, 99391
$
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Das ist genau das, was BlackJack meinte. Das ist Zufall und hat nichts mit der Version zu tun.

Dein Ablauf:
i=0
erster Thread startet
i=1
zweiter Thread startet
i=2


Die Threads laufen ja aber weiter, waehrend du das i hochzaehlst. Also kann mitten im Abarbeiten des ersten Threads i auf einmal schon 1 sein (du willst aber auf den nullten Index zugreifen). Und genauso kann im abarbeiten des zweiten Threads i schon 2 sein -> IndexError (du willst eigentlich auf den ersten Index zugreifen). Kann genauso gut sein, dass du Glueck hast und alles so laeuft, wie du dir denkst.

Wie gesagt, schmeiss den Index i raus. Globale Variablen=Pfui, Indeces=Pfui, beides zusammen=PfuiPfui. :wink:
d@tenmaulwurf
User
Beiträge: 7
Registriert: Dienstag 2. Mai 2006, 11:27

OK, Danke - habs jetzt soweit :)

Noch ne andere Frage bzgl. channel.recv(BYTE)
Wenn ich nicht weiß wie groß mein Stream wird, was gebe ich dann da an?
Kann ich das auf unbegrenzt schalten?
Ich will ja einen kleinen Proxy bauen - da weiß ich ja schließlich nicht, wieviel da rüber geht.
Antworten