Netværksprogrammering 3 - TCP server sockets

Tags:    c++
Skrevet af Bruger #2695 @ 09.03.2004

Introduktion


Så skal vi igen til at kode noget netværk. Denne gang skal vi kigge på server programmering, og som sædvanligt bygger vi videre på det projekt, vi har arbejdet med hidtil.
En server er et program, som tager imod indkommende opkald fra en klient. Derefter kommunikerer serveren og klienten indtil, forbindelsen afbrydes. En server kan godt servicere flere klienter samtidigt, og det kigger vi også på. Så er det jo rart, at vi allerede har kigget på multithreading, for det får vi brug for. Vi vil også synkronisere adgangen til klient objekterne, og det gør vi som beskrevet i artiklen om tråd synkronisering. Hvis du ikke har læst artiklerne om multithreading og tråd synkronisering, så kom i gang!!! Og tilføj Thread og Mutex klasserne til projektet.

En echo server


Projektet denne gang bliver en slags echo server. Traditionelt er en echo server et program, du forbinder til, siger noget til, og får det samme tilbage, hvorefter forbindelsen lukkes. De bruges ofte til tests.
Vores echo server tillader flere forbindelser samtidig og lukker først forbindelsen, når teksten "GOODBYE" modtages. Selve serveren lukkes når teksten "CLOSEDOWN" modtages.
Der er faktisk ikke mange nye funktioner at lære, fordi en server faktisk også er en socket. Man forbinder bare ikke sin socket nogen steder hen men binder den til en adresse og en port, som man vil lytte på, definerer hvor mange klienter, der skal være plads til i operativ systemets kø, og derefter kan man så acceptere klienter. Det gøres med følgende funktionskald:
Fold kodeboks ind/udKode 

Man bruger bind til at fortælle, hvilken netforbindelse og hvilken port, man vil lytte på. Hvis man kun vil acceptere forbindelser fra ét ud af flere netkort, så specificerer man IP adressen på dette netkort i my_addr. Ellers kan man specificere IN_ADDR_ANY for at tillade forbindelser fra alle netkort (inklusive loopback adressen 127.0.0.1).
listen opretter en kø i operativ systemet. Når en klient forbinder til din server, bliver han først lagt i denne kø, medmindre den er fuld. Så når dit server software har accepteret klienten (med accept), så fjernes han fra køen igen. Det betyder, at man ikke behøver at oprette en kø på 100, for at kunne servicere 100 klienter samtidig. 10 burde være mere end nok.
accept fjerner en klient fra køen og returnerer en socket, som kan kommunikere med denne klient. Denne funktion blokerer, men vi kan bruge select til at vente, og det gør vi på samme måde som i vores TCPSocket klasse.
Jeg har midliertidigt gjort den private constructor i TCPSocket klassen public for at kunne oprette objekter, som vores TCPServerSocket skal gøre det senere.
Vi prøver engang:
Fold kodeboks ind/udKode 


Føj for en masse kode. Godt vi skal pakke det ind senere og så aldrig se på det mere. Følgende billede viser et screenshot, hvor jeg har serveren kørende i øverste billede og telnetter med tre klienter. Første klient siger først "Hej, Verden" efterfulgt af "GOODBYE", hvorefter forbindelsen til ham bliver lukket. Anden klient siger "Hej fra mig" efterfulgt af "CLOSEDOWN", hvorefter forbindelsen til både ham og den sidste klient lukkes, og serveren lukkes ned.



Hvis du bruger Windows' version af telnet vil du måske få et problem, for den sender hvert tegn for sig. Du kan downloade Putty fra http://www.chiark.greenend.org.uk/~sgtatham/putty/. Det er en telnet (og meget andet) klient til Windows. Åben den, udfyld "Host Name (or IP address) feltet, sæt kryds i "Telnet" og skriv porten. Skift derefter til "Connection->Telnet" vinduet og sæt kryds i "Passive" under "Telnet negotiation mode" og tryk på "Open". Så skulle du få samme funktionalitet.

En TCPServerSocket klasse


Nu kan du godt gøre constructoren i TCPSocket privat igen, for nu kommer kommer TCPSocket's friend klasse, som jo kan bruge de private dele.
Vi vil straks gå videre med udviklingen af en klasse, til at indkapsle al denne funktionalitet. Jeg har defineret følgende interface til klassen, som jeg har valgt at kalde TCPServerSocket:
Fold kodeboks ind/udKode 

Her er implementeringen:
Fold kodeboks ind/udKode 

Revideret echo server


Nu er det så på tide at skrive vores echo server om, så den bruger vores TCPServerSocket klasse. Den første implementering var på 277 linjer mens den nye er på 202 linjer og lidt lettere at følge med i. Ændringen er udelukkende i include delen og i Server-klassens run() metode:
Fold kodeboks ind/udKode 

Jeg har tilføjet Mutex og TCPServerSocket koden til min Linux makefil:
Fold kodeboks ind/udKode 

Så er det så nemt at compile.

Konklusion


Det var alt, hvad jeg havde at sige om TCP netværks programmering, men legen slutter heldigvis ikke der. Vi kan nu slå netværks navne op i DNS, oprette forbindelser til servere og lave server programmer med meget få linjer kode. I næste artikel skal vi se på UDP sockets, så hæng på lidt endnu.


Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (3)

User
Bruger #2863 @ 31.05.05 17:56
Hej Robert

Bruger Dev-C++ under windows og får følgende fejl:

[Linker error] undefined reference to `TCPSocket::setTimeOut(unsigned int)'
[Linker error] undefined reference to `TCPSocket::~TCPSocket()'
[Linker error] undefined reference to `TCPSocket::read(void*, int)'
[Linker error] undefined reference to `operator<<(std::ostream&, Exception&;)'
[Linker error] undefined reference to `std::__default_alloc_template<true, 0>::deallocate(void*, unsigned int)'

... også videre

collect2 C:\\Programmer\\Dev-Cpp\\projekter\\echo server\\collect2 ld returned 1 exit status

C:\\Programmer\\Dev-Cpp\\projekter\\echo server\\Makefile.win [Build Error] ["Echo] Error 1

Jeg har tilføjet libws2_32.a til listen over filer til linkeren.

hilsen
Martin
User
Bruger #15047 @ 07.11.09 16:45
Hejsa. Jeg har lige læst og kigget denne artikel igennem. Men jeg har et spørgsmål, hvor har du alle de header filer fra?
Fold kodeboks ind/udC++ kode 
User
Bruger #15047 @ 07.11.09 20:26
Kan ikke redigere. :(
Men jeg har stadigvæk ingen af disse header filer. Jeg har kigget lidt på min Dev-C++ installation og umildbart kan jeg ikke finde dem. :(
Du skal være logget ind for at skrive en kommentar.
t