watki a łączenie z serwerem

0

Mam watek z takim run:

public void run()
        {
            while (true) { try {
                /*wy=polaczenie.getOutputStream();
                String komenda=jTextArea1.getText();

                if( komenda!=null && !(komenda.equals("")) )
                {
                    zapis = new DataOutputStream(wy);
                    zapis.writeBytes(komenda);
                }*/

                //we=polaczenie.getInputStream();
                odczyt= new BufferedReader (new InputStreamReader(we));
                String mud = "";
                while ((mud = odczyt.readLine())!=null)
                {
                        //jTextArea2.append("> \n");
                    if (mud!=null)  {
                        jTextArea2.append(mud+"\n");
                    } else if (mud==null && !(mud.equals("")) )
                    {
                        //jTextArea2.append("> ");
                    }
                }


             } catch(Exception e) { } }
                

        /* koniec metody run():   */
        }

Dlaczego pętla while(true) wykonuje sie tylko raz? Wątek się zakancza?

0

Jak byś dał wypis w bloku catch, to byś pewno się dowiedział...

Popełniłeś prosty błąd. Nie obsługujesz w żaden sposób wyjątków przez co nie wiesz co nie działa.

0

catch(Exception e) { System.out.println("e.getMessage(): " + e.getMessage()); }

Nie zwraca błędu.

Edit:
Serwer zwraca coś takiego:
" Blebleblbe
BlebleblbeBlebleblbeBlebleblbe
BlebleblbeBlebleblbeBlebleblbeBlebleblbe"
przerwa i znowu wysyła:
"Blebleblbe"

Działą mi tylko pętla wewnetrzna odczytująca wiersze pierwszej wyyslanej wiadomosci i otrzymuję:
" Blebleblbe
BlebleblbeBlebleblbeBlebleblbe
BlebleblbeBlebleblbeBlebleblbeBlebleblbe"

Natomiast po pierwszym przejsciu pętla sie kończy i dalej nie otrzymuję nic.

0

Ok. Czyli odpada najpoważniejsza przyczyna. Pytanie czy pętla wewnętrzna prawidłowo się wykonuje? Czy gdzieś nie zawisa na oczekiwaniu na znak końca linii/strumienia? IMO, powinieneś wydzielić kod obsługujący połączenie do osobnej metody i przetestować ją w środowisku jednowątkowym. Wtedy zobaczysz co tak naprawdę dzieje się w trakcie połączenia.

0

Dodałem na końcu pętli while ((mud = odczyt.readLine())!=null) :
jTextArea2.append("> ");
Piszę w netbeansie, a aplikacja jest okienkowa ;)

Wrzuca mi dokładnie 6 znaków : '>'
Więc pętla wewnetrzna obraca sie sześć razy i kończy się.
Cały wątek wygląda tak:


    class Watek2 extends Thread
    {
        Socket polaczenie;
        OutputStream wy;
        DataOutputStream zapis = null;
        InputStream we;
        BufferedReader odczyt = null;

        public Watek2(Socket polaczenie,OutputStream wy)
        {
            try{
                polaczenie= new Socket("serwer", port);
            } catch(Exception e){  }
            this.polaczenie=polaczenie;
            this.wy=wy;
        }

        public void run()
        {
            while (true ) { {try {
                /*wy=polaczenie.getOutputStream();
                String komenda=jTextArea1.getText();

                if( komenda!=null && !(komenda.equals("")) )
                {
                    zapis = new DataOutputStream(wy);
                    zapis.writeBytes(komenda);
                }*/

                we=polaczenie.getInputStream();
                odczyt= new BufferedReader (new InputStreamReader(we));
                String mud = "";
                while ((mud = odczyt.readLine())!=null)
                {
                        //jTextArea2.append("> \n");
                    if (mud!=null)  {
                        jTextArea2.append(mud+"\n");
                    } else if (mud==null && !(mud.equals("")) )
                    {
                        //jTextArea2.append("> ");
                    }
                    jTextArea2.append("> ");
                }


             } catch(Exception e) { jTextArea2.append("e.getMessage(): " + e.getMessage()); } }
                

        /* koniec metody run():   */
        }
    /* koniec klasy wew: */
    }

Chcę uzyskać efekt nasłuchiwania serwera, bo serwer sam wysyła treść, nie koniecznie w odpowiedzi na komendę.

Edit: Tylko jeden wątek jest aktywny, drugi jest do wyłączania tego pirewszego i nie działa.

0

To że obróciła się 6 razy to nie znaczy, że się skończyła. Może być tak, że oczekuje na kolejną linię i nie dostaje od serwera wartości null.

0

A normalnie mimo przerwy w przesylaniu danych powinno działać?

0

Tak. Bo readLine() oczekuje na znak końca linii. Zatem nawet jak nie ma transmisji to będzie wisiał. Swoją drogą popatrz na Netty, bo jeżeli nie musisz robić wszystkiego sam od początku to warto wykorzystać do komunikacji tą bibliotekę. Odpadną ci tego typu problemy.

0

Dzięki! Dziś tego nie sprawdze, ale olsnilo mnie. Twoja wypowiedz jest genialna w swojej prostocie. Niby to co npisales wiem, ale zaczalem nad tym myslec i bum. ;)
Otóż kiedy wpisze sie komende po ostatnim zdaniu zwracanym przez serwer, owa komenda nie jest w nastepnej lini tylko w tej samej, wniosek, nie ma znaku konca lini ;] Zupełnie o tym zapomnialem.

I z tego co kojarze podobnych przypadkow bedzie wiecej. Nie usmiecha mi sie korzystanie z read(), chyba ze jest metoda ktora zamienia mi znaki w int na stringa, pewnie jest, hm...
Jakas podpowiedz? :>

Wielkie dzięki raz jeszszcze, jestem baran :D [browar]

0

Możesz czytać sobie po int i następnie rzutować na char i dopisywać do StringBuildera/StringBuffera, ale jak nie masz konieczności to pisz ten serwer w Netty... jest naprawdę prosto.

0

a nie lepiej czytać bajtami i sam sobie ifem wybierać czy coś ma się kończyć czy nie? To oczywiście dotyczy sytuacji kiedy wiesz jaką formę wiadomości wysyła serwer.
Nigdy nie rozumiałem dlaczego używa się BufferedInputStream zamiast DataInputStream.
Z mojego doświadczenia z aplikacjami sieciowymi wielowątkowymi (bo jakze inaczej) wynika że do nasłuchu "komend" użyć readUTF a jak się wie że pójdzie coś z danymi to czytać do tablicy bajtowej. Ma się pełną kontrolę nad kodem: readUTF "wisi" do czasu otrzymania notyfikacji o nadchodzących danych a czytania bajtów pozbawia mnie wielu problemów które mogłyby się pojawić w readilajnie. To moja uwaga...jak komuś inaczej się sprawdza to nie przekonuje do zmieniania rozwiazań.

0

A jak jest z szybkoscia działania biblioteki Netty? Bo to dość ważny będzie aspekt tego klienta. Tymbardziej że java do demonów szybkości nie należy ;)

lipkerson napisał(a)

a nie lepiej czytać bajtami i sam sobie ifem wybierać czy coś ma się kończyć czy nie? To oczywiście dotyczy sytuacji kiedy wiesz jaką formę wiadomości wysyła serwer.
Nigdy nie rozumiałem dlaczego używa się BufferedInputStream zamiast DataInputStream.
Z mojego doświadczenia z aplikacjami sieciowymi wielowątkowymi (bo jakze inaczej) wynika że do nasłuchu "komend" użyć readUTF a jak się wie że pójdzie coś z danymi to czytać do tablicy bajtowej. Ma się pełną kontrolę nad kodem: readUTF "wisi" do czasu otrzymania notyfikacji o nadchodzących danych a czytania bajtów pozbawia mnie wielu problemów które mogłyby się pojawić w readilajnie. To moja uwaga...jak komuś inaczej się sprawdza to nie przekonuje do zmieniania rozwiazań.

jak zamienić ten fragment kodu:

we=polaczenie.getInputStream();
                odczyt= new BufferedReader (new InputStreamReader(we));
                String mud = "";
                while ((mud = odczyt.readLine())!=null)
                {
                        //jTextArea2.append("> \n");
                    if (mud!=null)  {
                        jTextArea2.append(mud+"\n");
                    } else if (mud==null && !(mud.equals("")) )
                    {
                        //jTextArea2.append("> ");
                    }
                    jTextArea2.append("> ");
                }

Tak aby użyć readUTF?
Bo mnie coś nie wyszło...
Czy to może oznaczać że serwer wysyła tekst którego to nie ubsłuży?

0

Czy readUTF() nie pobiera najpierw długości stringa, a potem tyle samo czyta? readLine() z kolei po prostu czyta wszystkie bajty aż do znaku nowej linii.

0

@daedin, netty jest szybki, a z powolnością Javy też bym nie przesadzał. swoją drogą dlaczego nie while(read()!=-1)? Nie będzie problemów....

0

Tego nie wiem, musieliby się wypowiedzieć bardziej doświadczeni ;)

Jak czytam sobie za pomocą .read() to mam problem z takimi znakami:

�(65533)�(65533)V(86)�(65533)

W nawiasie int znaku.
Zapewne Netty rozwiązuje tego typu problemy, ale niebardzo wiem gdzie szukać informacji o tej bibliotece.(bibliotece?)

0

hehe dokładnie też miałem taki problem :)

Zerknąłem do kodu i ja robie tak w skrócie:

DataInputStream indata;
DataOutputStream outdata;

indata = new DataInputStream(new BufferedInputStream(polaczenie.getInputStream()));
outdata = new DataOutputStream(new BufferedOutputStream(polaczenie.getOutputStream()));

I teraz jak mam pętlę do odczytów komend to mam:

String komendaSerwera = indata.readUTF(); 

if komendaSerwera jakaś to 
{
outdata .writeUTF("bla");
}

readUTF czeka aż coś pojawi się czyli wątek wisi do czasu przyjścia danych lub zerwania polaczenie. Ja takiej funkcjonalnosci potrzebowalem.

a jak ma przyjsc coś z danymi i dziwnymi znakami to robie

    System.out.println("Ilosc bajtow " + indata.available());
     byte[] dane = new byte[indata1.available()];
     indata.read(dane);
0

Rzecz w tym ze ja nie mam zadnego wpyływu na to co wysyła serwer.

0

Ale to nie chodzi o wpływ tylko o kolejność. Przeciez musisz wiedzieć co wyśle serwer-bo jak inaczej chcesz napisać klienta?

Jak jest serwer ftp i piszesz klienta ftp to wiesz co może przyjśc i w jakiej kolejnosci-chyba masz podobnie?

0

Humpf, wlasnie probowalem skorzystac z tego co mi napisales, troche mi nie wyszło.
Mógłbyś mi tutaj napisac cała moja funkcje run wątku, z wykorzystaniem tego co proponujesz?

Ogólnie serwer wysyła tylko tekst.

0

Nie mam teraz kompa z JDK...ogólnie tak jak miałeś. Przed wywołaniem runa wszystkie obiekty tworszysz służace do wymiany informacji a w runie pętla while i w niej readUTF. Jak wiesz ze tylko tekst bez jakiś znaków binarnych typu STX czy SQH to readUTF wystarczy. btw skad masz pewnośc że nie pojawi się od serwera jakiś STX?

Poka poka coś to napisał w tej klasie łączenia z serwerem.

0

Niebardzo rozumiem jak mam spradzać ilość bitów. Ja nie wiem kiedy przychodzą te śmiecie, wszystko idzie za pomocą telneta, czsami po prostu cos przyjdzie na koniec. A readUTF mi wisi.

Chyba serwer wysyła mi Extended ASCII. Jak mogę to obsłużyć?

0

Bez różnicy. UTF ma takie same znaki od 0-255 jak Ascii.

readUTF Ci wisi bo ma wisieć...jak się odwisi to znaczy ze coś przyszło-proste?

A odczytywanie bajtowe jest inne- sprawdzasz ile w DataInputStream przyszło bajtów...jak jest 0 tzn ze nic nie przyszło....przecież to proste.

while(true)
{
String zSerwera = polaczenie.readUTF();
*a tu co tam chcesz z tym robić oczywisćie przekazane do innego wątku by readUTF szybko wróił *do nasłuch.
}

A odczytywanie bajtowe to tak jak Ci napisałem.
Rozumiesz?

1 użytkowników online, w tym zalogowanych: 0, gości: 1