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? :(
Tcp-ip palvelimen toiminta.
5
520
Vastaukset
- kansantajuisen
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- kiireessä
tuli vähän tuplia :-)
- xor
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 ---- sittenkin... (xor)
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. - Pää Nyrjähtää
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 :)
Ketjusta on poistettu 0 sääntöjenvastaista viestiä.
Luetuimmat keskustelut
En löydä sinua
En löydä sinua täältä, etkä sinä varmaankaan minua. Ennen kirjoitin selkeillä tunnisteilla, nyt jätän ne pois. Varmaan k222351Eelin, 20, itsemurhakirje - Suomalaisen terveydenhuollon virhe maksoi nuoren elämän
Yksikin mielenterveysongelmien takia menetetty nuori on liikaa. Masennusta sairastava Eeli Syrjälä, 20, ehti asua ensi1062260- 522247
- 321527
Hajoaako persut kuten 2017?
https://www.is.fi/politiikka/art-2000011217813.html Tämä on totisinta totta. Persut on murroksessa. Osa jättää puolueen2381512- 301446
Kamala uutinen: Henkilö kuoli Tokmannin pihaan Kankaanpäässä- Jäi trukin alle
IL 9.5.2025 Ihminen kuoli Kankaanpään Tokmannin edustalla perjantaina aamupäivästä. Poliisin mukaan henkilö oli jäänyt361402- 951161
Ne oli ne hymyt
Mitä vaihdettiin. Siksi mulla on taas niin järjetön ikävä. Jos haluat musta eroon päästä niin älä huomioi mua. Muuten kä201136- 261126