Tcp-ip palvelimen toiminta.

Eli siis tahtoisin tietää miten oikeaoppisesti pitäisi rakentaa tcp-ip palvelin johon tulee jatkuvasti suuri määrä yhteyksiä.

Kuinka yhteyspoolia hanskataan fiksusti, entä datankäsittely kun yhteys on muodostettu, mitä käytännön ongelmia tulee jne jne jne... Mitä kannattaa pistää threadeihin ja miksi. Mitkä ovat kriittisiä asioita nopeuden kannalta. Miten samaan porttiin tulevat pyynnöt laitetaan fiksusti jonoon ja erotetaan toisistaan, kannattaako käyttää yhtä porttia vai avata joka clientille oma porttinsa vai vai vai jne jne jne...

Tästä aiheesta on hyvin vähän mitään helppotajuista/kokonaisvaltaista materiaalia. Voisiko joku valaista edes joltain kantilta? :(
5550
Äänestä

Muut lukivat myös

Vastaukset 5

Vanhimmat

aineiston puuttuminen johtunee siitä että asia ei ole mitenkään helppotajuista.
Gurujen ja Nörttien hommaa siis.

tuossa sekalaista rautaisannosta 10 sekunnissa googlattua:
http://www.google.fi/search?hl=fi&q=www palvelin&btnG=Hae&meta=cr=countryFI
http://www.google.fi/search?hl=fi&q=www palvelin&btnG=Hae&meta=cr=countryFI
http://www.cs.tut.fi/~jkorpela/
http://www.oulu.fi/tietohallinto/linkit/oppaat.html
http://www.google.fi/search?hl=fi&q=palvelimen pystytys&btnG=Google-haku&meta=cr=countryFI

Äänestä
  • tuli vähän tuplia :-)

    Äänestä

Jos jotain yleistä höpisisin. En sitten tiedä kuinka oikeassa olen asian ja termistön kanssa.

Samaan porttiin tulevat yhteydenottopyynnöt menevät automaattisesti jonoon, jonka pituus määrätään ns. backlog arvolla. Tätä jonoa ei tarvitse tehdä itse vaan käyttöjärjestelmä hoitaa sen. Jos palvelin ohjelma ei ehdi käsitellä tulevaa yhteydenottopyyntöä niin tällöin kyseinen jono takaa sen ettei yhteydenottopyyntöä menetetä.

Palvelin ohjelma käyttää yleensä vain yhtä yhteydenotto porttia (esim. 80 = HTTP) jota kautta asiakkaat (client) voivat ottaa siihen yhteyttä. Palvelin ohjelmassa on yksi sellainen säie joka kuuntelee (listen) yhteydenotto porttia (port) ja käsittelee siihen tulevat yhteyspyynnöt (eli käytännössä hyväksyy ne). Kun tämä säie hyväksyy (accept käskyllä) tulevan yhteydenotto pyynnön, niin tällöin koneiden välille muodostuu se varsinainen yhteys kahden vapaan portin välille. Tämän jälkeen kyseinen säie siirtää luomansa yhteyden käsittely jonoon ja palaa takaisin odottamaan uusia yhteydenottopyyntöjä.

Palvelin ohjelmisto pitää sisällään yleensä ns. säiealtaan (threadpool) jossa on valmiiksi luotuja käsittely säikeitä (thread). Käsittely säikeet ovat normaalisti lepotilassa odottelemassa sitä koska käsittely jonoon tulee uusi yhteys. Uuden yhteyden tullessa käsittely jonoon, ensimmäinen vapaa käsittely säie poimii sen ja ottaa käsittelyyn. Käsittely säie sitten käsittelee (eli lukee) sen asiakkaan pyynnön, antaa vastauksen (esim. HTML sivun), sulkee yhteyden ja palaa lepotilaan.

Kuormitetun palvelin ohjelmiston nopeuteen vaikutetaan ehkä kaikkein eniten optimoimalla käsittely säikeiden määrä sopivaksi. Yleisiä virheitä on varata tai luoda joka yhteydelle oma käsittely säie. Koska säikeen luominen on erittäin hidasta, niin tämän takia säikeet pitää luoda etu käteen (eli luodaan ns. säieallas). Joka yhteydelle ei kannata luoda omaa säiettä, koska säikeet syövät kone tehoa. On siis viisaampaa palvella osaa asiakkaista nopeasti, ja antaa muiden odottaa, kuin antaa kaikkien odottaa hitaan palvelun muodossa. Palvelimen toimintaa voi nopeuttaa myös käyttämällä erilaisia apusäkeitä. Joku säie voisi huolehtia tiedostojen käsittelystä siten että siinä olisi mukana myös ns. välimuisti ominaisuus, tms. Varsinaisen palvelun nopeuteen vaikuttaa aika paljon se miten sitä dataa sitten luetaan/kirjoitetaan, eli lähinnä puskurointi, jne.

Javalla yksinkertainen palvelin ohjelmisto voisi olla rungoltaan suunnilleen seuraavan kaltainen:


--- ALKU: Palvelin.java ---

import java.io.IOException;
import java.net.ServerSocket;

public class Palvelin {

   public static final int BACKLOG   = 300;
   public static final int PORT   = 80;
   public static final int THREADS = 20;

   public static void main(String[] args) throws IOException {
      YhteysJono yj = new YhteysJono();
      ServerSocket sc = new ServerSocket(PORT, BACKLOG);

      for (int i = 0; i < THREADS; i )
         (new KäsittelySäie(yj)).start();
      
      while(true)
         yj.lisaaYhteys(sc.accept());
   }
}

--- LOPPU: Palvelin.java ---


--- ALKU: YhteysJono.java ---

import java.net.Socket;
import java.util.Vector;

public class YhteysJono {

   private static int MAX_YHTEYKSIÄ = 500;

   private Vector yhteysJono;

   public YhteysJono() {
      yhteysJono = new Vector();
   }

   public synchronized void lisaaYhteys(Socket yhteys) {      
      yhteysJono.add(yhteys);

      do {
         notify();
      } while(yhteysJono.size() >= MAX_YHTEYKSIÄ);
   }

   public synchronized Socket annaYhteys() {
      while (yhteysJono.size() == 0) {
         try {
            wait();
         } catch (InterruptedException e) {
         }
      }

      return yhteysJono.remove(0);
   }
}

--- LOPPU: YhteysJono.java ---


--- ALKU: KäsittelySäie.java ---

import java.io.IOException;
import java.net.Socket;

public class KäsittelySäie extends Thread {
      
   private final YhteysJono yj;

   public KäsittelySäie(YhteysJono yj) {
      super();
      this.yj = yj;
   }
   
   public void run() {
      do {
         Socket s = yj.annaYhteys();

         /* Tähän varsinainen käsittely */
            
         try {
            s.close();
         } catch (IOException e) {
         }
      } while(true);
   }
}

--- LOPPU: KäsittelySäie.java ---

Äänestä
  • Kenties yhteys jonon seuraava koodi:

          do {
             notify();
          } while(yhteysJono.size() >= MAX_YHTEYKSIÄ);

    olisi sittenkin viisaampaa toteuttaa seuraavasti:

          do {
             notify();
             if (yhteysJono.size() >= MAX_YHTEYKSIÄ) {
                try {
                   wait(30);
                } catch (InterruptedException e) {
                }
             }
          } while(yhteysJono.size() >= MAX_YHTEYKSIÄ);

    Vector:n sijasta voi käyttää myös jotain nopeampaa lista rakennetta.

    Äänestä

  • Tää kuulosti nopeasti tutkittuna fiksulta ja oli juuri senkaltainen vastaus jota toivoin...

    Pitää lukea ja hahmotella tuo tekstisi oikein ajan kanssa kunnolla että hoksaa miten se toimii. On nimittäin himpun verran hankalaa...

    Kiitos tosiaan. Lisääkin saa neuvoa jos keksii jotain sanottavaa :)

    Äänestä

Kommentoi aloitusta


Pää nyrjähtää kirjoitti:

Eli siis tahtoisin tietää miten oikeaoppisesti pitäisi rakentaa tcp-ip palvelin johon tulee jatkuvasti suuri määrä yhteyksiä.

Kuinka yhteyspoolia hanskataan fiksusti, entä datankäsittely kun yhteys on muodostettu, mitä käytännön ongelmia tulee jne jne jne... Mitä kannattaa pistää threadeihin ja miksi. Mitkä ovat kriittisiä asioita nopeuden kannalta. Miten samaan porttiin tulevat pyynnöt laitetaan fiksusti jonoon ja erotetaan toisistaan, kannattaako käyttää yhtä porttia vai avata joka clientille oma porttinsa vai vai vai jne jne jne...

Tästä aiheesta on hyvin vähän mitään helppotajuista/kokonaisvaltaista materiaalia. Voisiko joku valaista edes joltain kantilta? :(

Anonyymi
5000

Ilmoita asiaton sisältö

  • Sisältää materiaalia, joka on loukkaavaa, herjaavaa, rasistista, uhkailevaa tai ahdistelevaa.

  • Materiaali sisältää nimiä, yhteystietoja tai muita henkilökohtaisia tietoja. Julkisuuden henkilöistä, julkisissa viroissa toimivista ihmisistä sekä yritysten vastuuhenkilöistä saa keskustella työhön liittyen. Myös yksityiselämään liittyvistä asioista voi keskustella siltä osin, kuin niistä on julkisesti kerrottu.

  • Sisältää lapsille haitallista tai heiltä kiellettyä materiaalia. Seksuaalinen sisältö on sallittua aiheeseen tarkoitetuilla palstoilla, joiden ikäraja on 18 vuotta.

  • Lainvastaista sisältöä voi olla mm. yksityiselämää loukkaavan tiedon levitys, kiihottaminen kansanryhmää vastaan, laiton uhkaaminen, alaikäisiin liittyvä seksuaalinen sisältö/grooming, petokset, identiteettivarkaudet, kunnianloukkaukset ja tekijänoikeusrikkomukset.

  • Sisältö ei liity palstan tai keskusteluketjun aiheeseen.

  • Viesti ei ole suomea tai ruotsia (pl. International Forums), se sisältää mainontaa, se sisältää tekijänoikeuksin suojattua materiaalia, se on massapostitus tai jokin muu syy.

Jaa keskustelu