Child pages
  • Socket problémák Servlettel
Skip to end of metadata
Go to start of metadata
Hello!
Azt szeretném kérdezni, hogy hogyan tudnék Sockettel kapcsolódni egy neten lévő Servlethez? Mindig "unknownHostException" hibát kapok, ha egy URL-t írok be...
Valaki segítsen!
      
      
Page viewed times
#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))
  • No labels

27 Comments

  1. Szerintem elírtad az URL-t. Ha esetleg bemásolnál egy kódrészletet.
    URLConnection conn = new URL("http://www.myserver.com/app/MyServlet").openConnection();
    InputStream in = conn.getInputStream();
    byte[] buffer = new byte[4096];
    while(true) {
      int count = in.read(buffer);
      if(count < 0) {
        break;
      }
      System.out.print(new String(buffer,0,count, "ASCII"));
    }
  2. Unknown User (gericop)

    Biztosan nem írtam el, mert a böngészőböl másoltam be... Nekem van egy tippem, a port száma nem tetszik neki... Amit beírtál kód azért nem jó, mert nekem folyamatos kapcsolatra van szükségem, nem egyszerire...
  3. Unknown User (gericop)

    Ez a kód:
    import java.io.*;
    import java.net.*;
    
    public class Client
    {
        public static void main(String[] rr)
        {
            try
            {
                Socket s = new Socket("http://myjavaserver.com/servlet/gericop.FirstServlet",80);
                PrintWriter pw = new PrintWriter(s.getOutputStream());
                pw.println("TEST");
                pw.flush();
            } catch (Exception e) {System.err.println(e);}
        }
    }
  4. A gericorp.FirstServlet érvénytelen ilyen esetben - szerintem. Vagy hogy az url közepén van egy pont. Próbáld meg string helyett egy
    new Socket(new URL("http://myjavaserver.com:80/servlet/gericop.FirstServlet"));
    Vagy csak FirstServlet, és a web.xml-ben kell megadni a konkrét mappinget.
  5. Unknown User (gericop)

    Socket-nek nincs URL-os paramétere... A lényeg az, h el szeretném érni a folyamatos kapcsolatot egy cliens alkalmazás és egy servlet között... Ha valaki tudna ilyen kódot mutatni, szóljon!
  6. Ezzel a kóddal már minden világos... :)

    A Socket nem http protokoll stack! A Socket-nek adni kell egy IP címet (vagy hostnevet), egy portot és neked kell levezényelni a teljes kommunikációt. Például így:
        try
        {
            Socket s = new Socket("myjavaserver.com",80);          
            PrintWriter pw = new PrintWriter(s.getOutputStream());
            pw.println("GET /servlet/gericop.FirstServlet HTTP/1.0\n");
            pw.println("Host: myjavaserver.com\n");
            pw.println("\n");
            pw.flush();
            BufferedReader br= new BufferedReader(new InputStreamReader(s.getInputStream()));
            System.out.println(br.readLine());
            br.close();
        }
        catch (Exception e)
        {
            System.err.println(e);
        }
    Próbáld ilyenféleképp.
  7. Unknown User (gericop)

    Még aszongya meg vki, h kell azt megcsinálni, h ne zárja le a kapcsolatot a kliens és a server között?
    Ez alapján dolgoztam: http://codefasga.com/tutorials.php?id=2
    Ez lezárja a kapcsolatot... Próbálkoztam mindennel, de sehogy sem akarja megtartani.
  8. Esetleg az Apache HTTP Client implementációja segíthet. Bár szerintem fontos még a
     Connection: keep-alive
    paraméter átadása a webservernek, mert az becsukja a servlet futása után különben, és akkor ugyanott vagy, mint az URLConnection esetében. De amúgy is, hiszen a servletek általában nem végtelen ciklusban futnak, és ráadásul nem kapják meg az inputstreamet (?), úgyhogy nem fog menni a párbeszéd. Erre külön szálon kell egy ServerSocket-et indítani, amivel TCP szinten beszélgethetsz.
  9. Unknown User (gericop)

    Igen, ServerSocket van nyitva a servletben, de lezárja, amint kapott egy input adatot...
  10. Mivel HTTP-re kapcsolódsz, a HTTP stateless jellegű, lezajlik a kérés-válasz tranzakció és a _szerver_ bontja a kapcsolatot a keepalive idő lejárta után, illetve bizonyos számú kérés kiszolgálása után is.

    Akkor fog menni ez a Socket jellegű kapcsolattartás, ha a szerver oldal is nyit egy socket-et, és arra a portra kapcsolódsz. Kérdés, hogy ezt engedi-e az adott szerver tűzfala...

    Felmerül a kérdés, hogy mire kell?
  11. Igen, ServerSocket van nyitva a servletben, de lezárja, amint kapott egy input adatot...
    Ha nyitsz egy Socket-et a szerveren a servletben, akkor az biztos, hogy nem fog a 80-as porton hallgatózni, mert ott egy Apache vagy egy Tomcat van.
  12. Remek jelölt egy protokoll létrehozására:
    Irsz egy szervletet, ami egy port paramétert vár vagy ad vissza eredményként, amin elindít egy új ServerSocket alapú TCP szervert, és a kliens oldalon kezdeményezett szimpla URLConnection segítségével lehet beizzítani (leállítani). Így a visszakapott portszámot fel tudod használni a kliens oldalon egy Socket nyitásához.
  13. Unknown User (gericop)

    A 9990-es port van megnyitva, de úgyanúgy zár (pontosabban az előbb leírt Socket csatlakozós kóddal el sem jut odáig...).
  14. Unknown User (gericop)

    Egy hiba már megvan... Nem tud portot nyitni... Most tudnom kéne, melyik portokat lehet nyitni...
  15. Csak úgy nem szokta bezárni, kivéve esetleg mert a GC lenyomja a ServerSocketet referencia hiány miatt. Próbáld meg az inicializáló osztályban static-ként felvenni, illetve egy külön figyelő szálat indítani a serversocketnek:
    Thread t = new Thread(new Runnable() {
      public void run() {
        ServerSocket ss = null;
        try {
          ss = new ServerSocket(9900);
          while(!isInterrupted()) {
             Socket s = ss.accept();
          }
        } catch(IOException) {
        } finally {
           if (ss != null) {
               try {
                   ss.close();
               } catch(IOException exc) {
               }
           }
        }
      }
    });
    t.setDaemon(true);
    t.start();
  16. A 9990 port zárva vagyon...
    $ nmap -p 9990 myjavaserver.com
    
    Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2007-02-11 18:50 CET
    Interesting ports on cp4.javalobby.org (64.69.35.205):
    PORT     STATE  SERVICE
    9990/tcp closed unknown
    Csodálkoznék, ha a myjavaserver.com szerveren csak úgy engednének portot nyitni. Én legalábbis tiltom a befelé érkező SYN csomagokat azokra a portokra, amelyeken nem figyel felügyelt szolgáltatás. A szerver természetesen kezdeményezhet kifelé kapcsolatot, a másik oldal pedig ekkor már ACK-ot küld, ami átmegy a tűzfalon.

    Mire kell, amit nem tudsz megoldani HTTP protokollon? Gondolom arra, hogy a kliens figyel, a szerver meg küld üzenetet valamilyen esemény bekövetkeztekor. Ezt meg tudod csinálni HTTP-n is, egyszerűen a kliens felcsatlakozik, a szerver pedig csak akkor ad választ, ha az esemény bekövetkezik. Az esemény lekezelése után a kliens újra felkapcsolódik a szerverre... Ez a módszer nem jó?
  17. A myjavaserver.com az csak egy placeholder, vagy a tényleges oldal? Attól függ, ki az admin ott. A felcsatlakozva maradás nem túl jó ötlet, mert a HTTP szabványban 30s van megadva timeoutra alapból. Habár a HTTP magában stateless, de a szerver oldali session (+session cookie) pont lehetőséget ad a statefull viselkedésre.

  18. Unknown User (gericop)

    Ha valaki tudna mutatni vmi nagyon alap servlet és client kódot, azt megköszönném...
  19. A felcsatlakozva maradás nem túl jó ötlet, mert a HTTP szabványban 30s van megadva timeoutra alapból.
    Ezzel az idővel én csak php oldalakon találkoztam script timeoutként... egy HTTP session tarthat akár több napig is, hiszen akár egy több GBájt méretű állományt is tölthetünk éppen. Fura lenne, ha megszakadna a kapcsolat fél percenként. És az, hogy a szerver adatot küld, vagy vár, az teljesen mindegy.
  20. Ez a timeout vagy a kliens oldalon, vagy a szerver oldalon szokott megjelenni, és abban az esetben, ha 30s-ig nincs abszolút semmi aktivitás a csatornán (még keepalive sem). Vagy keverem a connection timeouttal?
  21. Unknown User (gericop)

    Valaki nem tudna mutatni egy példát (forráskódot)? A "server"-nek nem kell feltétlenül servletben lennie...
  22. Ez a timeout vagy a kliens oldalon, vagy a szerver oldalon szokott megjelenni, és abban az esetben, ha 30s-ig nincs abszolút semmi aktivitás a csatornán
    Hát... ez csak attól függ, hogy az adott HTTP kliens vagy szerver mit ír elő timeout-ként... böngészőnként és webszerverenként más-és-más ez az érték. Ha a szerver és a kliens is a Te kezedben van, akkor olyan időt írsz elő, amennyit akarsz...

    Én ilyen szabványról nem tudok, hogy konkrét időket írnának elő...
  23. Valaki nem tudna mutatni egy példát (forráskódot)?
    Mit szeretnél csinálni? Hátha van alternatíva. :)
  24. Unknown User (gericop)

    Kéne egy server alkalmazás, amihez több client is tudna kapcsolódni... Olyasmi, mint egy chat...
  25. Unknown User (gericop)

    Nah? Nem tud senki sem segíteni?! :(
  26. Nah? Nem tud senki sem segíteni?! :(
    Socket-el nemigen fog menni. Nem erre való... idegen szerveren nem tudsz portot nyitni. Azt tudod tenni, hogy a HTTP protokollt használod Socket jellegű burokban. A kliens minden egyes kérés-válasz után újra felkapcsolódik a szerverre, a szerver pedig addig nem küld adatot a csatornába, amíg nincs esemény. Ezzel megoldottad azt, hogy a szerver tudjon "üzenni" a kliensnek.

    Kevésbé terhelő, ha a kliens 1-2-5 másodpercenként újrakérdezi a szervert.
  27. Amit karnokd írt kódrészlet, az már majdnem teljesen működőképes szerver rész. Annyit kell még vele csinálni, hogy a Socket s = ss.accept(); után a socket-et megfelelően kezeled. Pl:
    ClientThread ct = new ClientThread(s);
    clients.add(ct); //clients egy List például, amiben tárolva vannak a kliensek.
    ct.start();
    Ahol:
    class ClientThread extends Thread {
        private Socket s;
        public ClientThread(Socket s) {
           this.s = s;
        }
        public void run() {
           //try catch block + thread stop kezelés.
           int ch;
           while((ch=s.read())>=0) {
              ...//stream-ből való karakter beolvasás kezelése.
              //pl. kiírni az összes többi kliensre.
           }
        }
        public void send(int ch) {
           //try catch
           s.write(ch);
        }
    }
    Ez csak egy vázlat, csomó minden hiányzik belőle, pl. a hibakezelés is.