Strona 1 z 2 12 OstatniOstatni
Pokaż wyniki 1 do 10 z 12

Temat: Problem z nasluchiwaniem

  1. #1
    Zarejestrowany
    Jul 2008
    Postów
    18

    Domyślnie Problem z nasluchiwaniem

    Witam,
    mam cos takiego:
    Kod:
    $p = IO::Socket::INET->new(LocalPort=>2345, Listen=>1, ReuseAddr=>1);
    $w = $p->accept();
    print $w->peerhost, ": ", <$w>;
    Po odebraniu jednego pakietu skrypt sie wylacza a chcial bym zeby ciagle odbieral pakiety do momentu wylaczenia go lecz nie wiem w jaki sposob to zrobic. Gdy daje "while(1)" to po pierwszym odebraniu skrypt sie wysypuje. Z gory thx za pomoc.

    Problem rozwiazany:
    Kod:
    $p = IO::Socket::INET->new(LocalPort=>2345, Listen=>1, ReuseAddr=>1);
    while(1)
    {
    $w = $p->accept();
    print $w->peerhost, ": ", <$w>;
    }
    Ostatnio edytowane przez user : 07-29-2008 - 17:09

  2. #2
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    powinno byc

    Kod:
    while ($w = $p->accept()) {
       print $w->peerhost, ": ", <$w>;
    }
    zobacz manual IO::Socket - po sieci dodatkowo wala sie masa przykladow, pierwszy strzal z google daje gotowca... http://www.rocketaware.com/perl/perl..._IO_Socket.htm
    ctrl-alt-del.cc - soft reset site for IT admins and other staff :-)

  3. #3
    Zarejestrowany
    Jul 2008
    Postów
    18

    Domyślnie

    Proboje zrobic zeby ciagle sprawdzalo czy sa jakies pakiety i jednoczesnie sprawdzalo czy jest cos na wejsciu a jesli tak to zeby to wysylalo
    Kod:
    $p = IO::Socket::INET->new(LocalPort=>2345, Listen=>1, ReuseAddr=>1);
    $conn = IO::Socket::INET->new(PeerPort=>2345,PeerAddr=>'localhost');
    
    while (1)
    {
    if($w = $p->accept()) 
    {
    print "----------\n| ", $w->peerhost, ": ", <$w>, "----------\n";
    }
    if($text = <STDIN>)
    {
    print $conn $text;
    }
    }
    ten kod niestety nie dziala...
    Wie ktos jak rozwiazac ten problem?

  4. #4
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Tak... zajrzec do strony do ktorej link podalem w poscie powyzej - tam masz gotowca leniu jeden... i to dokladnie czytajacego z socketa tak jak chcesz...
    ctrl-alt-del.cc - soft reset site for IT admins and other staff :-)

  5. #5
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Przyznaje sie bez bicia, za szybko zamknalem watek. user napisal do mnie na PM i mial calkowita racje, wiec otwieram watek ponownie i przepraszam za zbyt szybkie zamkniecie.

    Dla wyjasnienia co w Twoim kodzie bylo nie tak...

    Petla while ($conn = $socket->accept()) ... odpowiada za zaakceptowanie polaczen i rozpoczecie ich obslugi. Problem w tym, ze dalej czytales z STDIN, zamiast czytac z $conn. W Perlu STDIN to uchwyt pliku, tak samo jak uchwyt, ktory powstaje przy uzyciu funkcji open(). Na dobra sprawe nasza zmienna $conn bedzie sie zachowywac tak samo jak uchwyt pliku. Jesli wiemy ze protokol jest tekstowy to mozna czytac tak samo jak z pliku...
    Kod:
    while (<$conn>) {
       # teraz zmienna $_ zawiera kolejne linie wchodzace z socketa
    }
    niestety w swoim kodzie czytales z STDIN... link powyzej znaleziony w google pokazuje gotowy kawalek czegos jak prosty chat-server, do ktorego wysyla sie polecenia tekstowe i on cos dalej robi.
    ctrl-alt-del.cc - soft reset site for IT admins and other staff :-)

  6. #6
    Zarejestrowany
    Jul 2008
    Postów
    18

    Domyślnie

    Jesli dobrze zrozumialem co napisales to chyba troche zle wytlumaczylem... nie chodzi mi o czytanie tego co jest do mnie wysylane. Zacznijmy od poczatku, napisalem skrypt:
    Kod:
    #!/usr/bin/perl
    use IO::Socket::INET; 
    sub put
    {
    my($text) = @_;
    $conn = IO::Socket::INET->new(PeerPort=>2345,PeerAddr=>'localhost');
    print $conn $text;
    }
    sub get
    {
    my($socket) = @_;
    $conn = $socket->accept();
    print "----------\n| ", $conn->peerhost, ": ", <$conn>, "----------\n";
    }
    $socket = IO::Socket::INET->new(LocalPort=>2345, Listen=>1, ReuseAddr=>1);
    while(1)
    {
    if($text = <STDIN>)
    {
    put($text);
    }
    get($socket);
    }
    Odpalam go w teminalu, pisze "text" i dostaje:
    ----------
    | 127.0.0.1: text
    ----------

    ale jesli wysle ze skrytu2 np "asd" na port na ktorym nasluchuje skrypt1 to nie pokaze mi sie nic, dopiero po wcisnieciu entera dostane tamta wiadomosc tak jakby dodaja sie do kolejki. Chce zeby byly wyswietlane na bierzaco czyli zeby wejscie <STDIN> bylo sprawdzane czy cos tam jest ale zeby skrypt nie czekal az cos zostanie tam podane tylko wykonywal sie dalej aby wyswietlac tekst ktory trafia na port na ktorym nasluchuje skrypt.

  7. #7
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    tzn jesli dobrze rozumiem, chcesz napisac cos w rodzaju czata ale tak aby bylo widac jak rozmowca wbija kolejne litery a nie przesylanie tekstu calymi liniami, tak?

    Normalnie Perl czyta teksty liniami i jest to bardzo rozsadne. Problem polega na tym, ze zdefiniowales 2 funkcje, put($text) i get(). Niestety kazda z funkcji tworzy swoj socket na podanym porcie, wiec pierwsza funkcja zrobi swoje i nadal trzyma socket otwarty a druga ktora zostanie odpalona (get) juz nie dostanie sie do portu - port in use.

    Sztuka w zasiegu zmiennych - jesli definiujesz socket w ramach funkcji, jest on dostepny tylko w ramach funkcji. Proponuje abys zaczal pisac z uzyciem modulu strict i wtedy bedziesz musial jasno definiowac zakresy zmiennych - na poczatku to denerwuje ale sie bardzo przydaje przy debugowaniu.

    No wiec zrobmy dzialajacy przyklad...

    Kod:
    #!/usr/bin/perl
    use IO::Socket::INET; 
    use strict;
    
    # wylaczamy buforowanie terminala i uchwytow plikow
    # czasami program nic nie wyswietli do czasu zamkniecia strumienia
    $|++;   
    
    # ta funkcja wysyla przez socket
    sub put {
      # zmoienne sa lokalne, istnieja tylko wewnatrz procedury
      my ($conn, $text) = @_;
      print $conn $text;
    }
    
    # tutaj czytamy dane z uchwytu polaczenia, jak z pliku
    sub get {
      my $conn  = $_[0];   # my ($conn) = @_;  -- inaczej zapisane
      # wczytujemy jedna linie - wazne aby to byla osobna operacja, 
      # bo wewnatrz print'a czasami glupieje
      chomp (my $text = <$conn>);   
      print "----------\n| ", $conn->peerhost, ": $text\n----------\n";
    }
    
    # tworzymy sobie socket na ktorym bedziemy sluchac,
    # dlugosc kolejki dajemy pro-forma na 5 polaczen, port 23 (telnet) i TCP
    # jesli port jest zajety dostaniemy blad i program zakonczy prace
    my $socket = IO::Socket::INET->new(Listen => 5,
            LocalAddr => 'localhost',
            LocalPort => 23,
    	Proto => 'tcp',
    	) or die "Nie moge zaczac sluchac na porcie: [email protected]\n";
    
    
    # akceptujemy dokladnie 1 polaczenie, nie ma petli!
    
    my $conn = $socket->accept();
    # grzecznie zapytajmy czego chce nasz gosc
    print $conn "Co slychac?\n";
    get($conn);
    # odczytalismy tekst i wyswietlilismy, to czas odpowiedziec
    print "Odpowiedz: ";
    my $odp = <STDIN>;
    # to mozna tak samo jak wyzej z "co slychac"
    put($conn, $odp);
    # zamykamy socket w poprawny sposob...
    $conn->close();
    kod akurat zrobilem i sprawdzilem pod windows i dziala...
    ctrl-alt-del.cc - soft reset site for IT admins and other staff :-)

  8. #8
    Zarejestrowany
    Jul 2008
    Postów
    18

    Domyślnie

    Ja potrzebuje czegos dokladnie takiego:
    Kod:
    while(1)
    {
    if(jest cos w <STDIN>)
    {
    #wysyla pakiet z textem z <STDIN> do ip wczesniej zdefiniowanego
    }
    else
    {
    #czyta pakiety ktore dostajemy
    }
    }
    To ma dzialac tak ze mozesz napisac pare wiadomosci i one sie wyswietla w drugim oknie i z drugiego okna w dowolnym momencie mozesz pisac. To ma dzialac jak czat tyle ze nie moze czekac na wprowadzenie danych do <STDIN> tylko musi sprawdzac czy te dane juz sa.
    Ostatnio edytowane przez user : 07-30-2008 - 08:35

  9. #9
    Zarejestrowany
    Jul 2008
    Postów
    18

    Domyślnie

    Kod:
    STDIN->blocking(0);
    Wylacza oczekiwanie na text na wejsciu.

  10. #10
    Zarejestrowany
    Jun 2006
    Skąd
    rand(.eu)
    Postów
    8,748

    Domyślnie

    Cytat Napisał user Zobacz post
    To ma dzialac tak ze mozesz napisac pare wiadomosci i one sie wyswietla w drugim oknie i z drugiego okna w dowolnym momencie mozesz pisac. To ma dzialac jak czat tyle ze nie moze czekac na wprowadzenie danych do <STDIN> tylko musi sprawdzac czy te dane juz sa.
    To bardzo fajnie ale ma jeden problem... kazda wiadomosc przesylana bedzie oznaczala nowe polaczenie TCP - ehmmm straci sporo na predkosci...

    Teraz niestety nie mam czasu nad tym siasc ale pomysle jak bede mial chwilke jak to fajnie jakos zapisac. Zastanawia mnie tylko jedno... dlaczego to wyglada dokladnie tak samo jak program talk z unixow
    ctrl-alt-del.cc - soft reset site for IT admins and other staff :-)

Strona 1 z 2 12 OstatniOstatni

Zasady Postowania

  • Nie możesz zakładać nowych tematów
  • Nie możesz pisać wiadomości
  • Nie możesz dodawać załączników
  • Nie możesz edytować swoich postów
  •  
Subskrybuj