Thread Problem mit Sockets und Threads - IRC-Gateway
(14 answers)
Opened by Paul321 at 2011-08-08 15:06
Beispiel für eine verwaltete Kommunikation zwischen zwei Threads:
Code (perl): (dl
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 #!/usr/bin/perl use warnings; use strict; use threads; use threads::shared; # Daten für die Threads my %threads=(); # für jeden thread gibt es drei Werte, # die über den thread hinaus gelesen werden können # end => thread hat sich beenden, oder soll sich beenden # txt_print => Puffer für den anzuzeigenden Text # txt_send => Puffer für den "eingebenden" Text #----------------------------------------------------------------------- # Daten Thread A share($threads{a}{end}); share($threads{a}{txt_print}); share($threads{a}{txt_send}); $threads{a}{end}=0; $threads{a}{txt_print}=''; $threads{a}{txt_send}=''; $threads{a}{name}='Thread_A'; $threads{a}{'shift'}=0; #----------------------------------------------------------------------- # Daten Thread B share($threads{b}{end}); share($threads{b}{txt_print}); share($threads{b}{txt_send}); $threads{b}{end}=0; $threads{b}{txt_print}=''; $threads{b}{txt_send}=''; $threads{b}{name}='Thread_B'; $threads{b}{'shift'}=35; #----------------------------------------------------------------------- # Thread a starten $threads{a}{thread}=threads->new(\&work,$threads{a}); # Thread b starten $threads{b}{thread}=threads->new(\&work,$threads{b}); # haupttread loop # hier werden die Nachrichten verteilt # solange arbeiten wie ein Thread noch läuft. while(1) { my $exit=0; my($n1,$n2)=qw(a b); communicate($threads{a},$threads{b}); communicate($threads{b},$threads{a}); last if($threads{a}{end} || $threads{b}{end}); # ein wenig warten sleep(1); } # Beenden erzwingen # und auf das Ende warten $threads{a}{end}=1; $threads{b}{end}=1; $threads{a}{thread}->join(); $threads{b}{thread}->join(); exit; ######################################################################## ######################################################################## # das ist der einzelne Thread sub work { my $data=shift; # mindestens 10 maxinal 20 Durchläufe my $count=int(rand(10))+10; while(1) { # zufälliger String von 10 Zeichen länge my $str=join('',map{chr(33+int(rand(93)))}(0..10)); # Text an den Puffer anhängen # beim überschreiben könnten Daten verloren gehen, # wenn der Puffer noch nicht geleert wurde $data->{txt_send}.="$str\n"; # es soll Text angezeigt werden if($data->{txt_print}) { # Text lesen und "Puffer" leeren # das sollte möglichst atomar sein, # sonst könnte ein anderer Thread da zwischen funken my $text=$data->{txt_print}; $data->{txt_print}=''; # Ausgabe # Text formatieren my $shift=' 'x$data->{'shift'}; $text=~s/\n$//s; $text=~s/(^|\n)/$1$shift$data->{name}: /gs; print "$text\n"; } # wenn counter abgelaufen # dann Signal zum beenden setzen $data->{end}=1 if($count-- <= 0); # beenden wenn das Signal kommt last if($data->{end}); # zufällig lang warten (0..1 Sekunde) select(undef,undef,undef,rand(1)); } } # Daten wischen den einzelnen Kind-Threads austauschen sub communicate { my ($from,$to)=@_; # wenn Text gesendet wurde # dann formatieren und an den anderen senden if($from->{txt_send}) { # EingabePuffer lesen und leeren my $text=$from->{txt_send}; $from->{txt_send}=''; # formatieren und in AusgabePuffer schreiben $text=~s/\n$//s; $text=~s/(^|\n)/$1$from->{name} => /gs; $to->{txt_print}.="$text\n"; } # beenden Nachricht senden wenn nötig if($from->{end} && !$from->{end_ok}) { $to->{txt_print}.="$from->{name} hat sich beendet!\n"; $from->{end_ok}=1; } } |