TCP szerver készítése



Hasonló dokumentumok
Hálózati architektúrák laborgyakorlat

Dr. Varga Imre Debreceni Egyetem, Informatikai Kar. Socket-programozás. C nyelven, Linux alatt

Számítógépes hálózatok I.

Dr. Varga Imre. Socket-programozás. C nyelven

Számítógépes hálózatok

Számítógép-hálózatok: 4. Labor. TCP kliens. A gyakorlat célja:

Számítógépes Hálózatok. 9. gyakorlat

SOCKET használata UDP kliens

Bevezetés a SOCKET programozásba UDP kliens

Számítógépes Hálózatok GY 3-4.hét

Számítógépes hálózatok

TCP szerver. TCP szerver alkalmazás írásának az elsajátítása TCP protokoll tulajdonságainak a tanulmányozása kisérleti úton

Számítógépes Hálózatok. 3. gyakorlat

Beej útmutatója a hálózati programozáshoz

Programozás I. gyakorlat

UDP idő szerver. UDP protokollal kapcsolatos ismeretek elmélyítése. Egy UPP protokollt használó időszerver megvalósítása

Socket programozás Példák

A Wireshark program használata Capture Analyze Capture Analyze Capture Options Interface

TCP/IP SOCKET INTERFACE

Szövegek C++ -ban, a string osztály

Járműfedélzeti rendszerek II. 3. előadás Dr. Bécsi Tamás

Szilipet programok telepítése Hálózatos (kliens/szerver) telepítés Windows 7 operációs rendszer alatt

Occam 1. Készítette: Szabó Éva

Számítógépes Hálózatok. 5. gyakorlat

Programozás 6. Dr. Iványi Péter

Programozás C és C++ -ban

1. Alapok. #!/bin/bash

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus változók. Dinamikus változók. Dinamikus változók. Dinamikus változók. 7.

Számítógép labor V. Egyszer Web szerver. Dokumentáció. Készítette: Ács Gergely (K4C03M)

Számítógépes Hálózatok. 3. gyakorlat

Programzás I gyakorlat

A C programozási nyelv V. Struktúra Dinamikus memóriakezelés

A C programozási nyelv VI. Parancssori argumentumok File kezelés

C programozási nyelv Pointerek, tömbök, pointer aritmetika

FTP: Elkülönített kontroll- és adatkapcsolat. FTP: File Transfer Protocol

Programozás II. 2. Dr. Iványi Péter

C programozási nyelv

Socketek programozása

UNIX: folyamatok kommunikációja

Számítógépes Hálózatok GY 6.hét

Gyorstalpaló hálózatprogramozás C nyelven UNIX. környezetben

Programozás alapjai gyakorlat. 2. gyakorlat C alapok

Bevezetés, a C++ osztályok. Pere László

Függvény pointer. Feladat: Egy tömbben soroljunk fel függvényeket, és hívjuk meg valahányszor.

Számítógépes Hálózatok GY 3.hét

4. Laborgyakorlat. A fájlokról ezeket az adatokat, a fájlrendszer tárolja. Számunkra az 1, 3, 4. oszlopok lesznek az érdekesek.

Operációs rendszerek. 6. gyakorlat: Processzusok közti kommunikáció (osztott memória, üzenetsor)

Megoldás. Feladat 1. Statikus teszt Specifikáció felülvizsgálat

Kommunikáció. Távoli eljáráshívás. RPC kommunikáció menete DCE RPC (1) RPC - paraméterátadás. 3. előadás Protokollok. 2. rész

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

Hálózatos adatbázis-kapcsolódási problémák és azok javítása

Java II. I A Java programozási nyelv alapelemei

Számítógépes Hálózatok. 4. gyakorlat

Számítógépes Hálózatok. 7. gyakorlat

[SZÁMÍTÓGÉP-HÁLÓZATOK]

Programozás alapjai 9.Gy: Struktúra 2.

Mechatronika és mikroszámítógépek 2017/2018 I. félév. Bevezetés a C nyelvbe

Függvények. Programozás I. Hatwágner F. Miklós november 16. Széchenyi István Egyetem, Gy r

Számítógépes Hálózatok 2012

Számítógépes Hálózatok GY 4.hét

Már megismert fogalmak áttekintése

Számítógépes Hálózatok GY 7.hét

III. Felzárkóztató mérés SZÉCHENYI ISTVÁN EGYETEM GYŐR TÁVKÖZLÉSI TANSZÉK

Programozási alapismeretek beadandó feladat: ProgAlap beadandó feladatok téma 99. feladat 1

Programozás alapjai 2.Gy: A C nyelv alapjai P R O

C programozási nyelv

Delphi programozás I.

1. Alapok. Programozás II

C programozás. 6 óra Függvények, függvényszerű makrók, globális és

URL-LEL ADOTT OBJEKTUM LETÖLTÉSE (1) URL-LEL ADOTT OBJEKTUM LETÖLTÉSE

1. Bevezető. 2. IP cím és szolgáltatások felderítése

OOP #14 (referencia-elv)

Járműfedélzeti rendszerek II. 4. előadás Dr. Bécsi Tamás

Mintavételes szabályozás mikrovezérlő segítségével

II. Mérés SZÉCHENYI ISTVÁN EGYETEM GYŐR TÁVKÖZLÉSI TANSZÉK

Számítógép hálózatok gyakorlat

Interfészek. PPT 2007/2008 tavasz.

Programozás I. 5. Előadás: Függvények

Kommunikáció. 3. előadás

SSL elemei. Az SSL illeszkedése az internet protokoll-architektúrájába

SSL VPN KAPCSOLAT TELEPÍTÉSI ÚTMUTATÓ

Programozás I gyakorlat

Mobil Partner telepítési és használati útmutató

1. Bevezetés szeptember 9. BME Fizika Intézet. Szám. szim. labor ea. Tőke Csaba. Tudnivalók. feladat. Tematika. Moodle Házi feladatok

Óbudai Egyetem. C programozási nyelv

A virtuális környezetet menedzselő program. Első lépésként egy új virtuális gépet hozzunk létre a Create a New Virtual Machine menüponttal.

Az internet ökoszisztémája és evolúciója. Gyakorlat 1

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

Konkurens TCP Szerver

Operációs rendszerek. 9. gyakorlat. Reguláris kifejezések - alapok, BASH UNIVERSITAS SCIENTIARUM SZEGEDIENSIS UNIVERSITY OF SZEGED

C string műveletek (string.h alkalmazása)

Programozás C nyelven FELÜLNÉZETBŐL elhullatott MORZSÁK. Sapientia EMTE

Programozás 1. Dr. Iványi Péter

Vectory telepítési útmutató

Programozás II. Fájlkezelés

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában

Programozás I gyakorlat. 10. Stringek, mutatók

3. Ezután a jobb oldali képernyő részen megjelenik az adatbázistábla, melynek először a rövid nevét adjuk meg, pl.: demo_tabla

12. gyakorlat Enum; Tárolási osztályok Preprocesszor utasítások; Moduláris programozás

Átírás:

TCP szerver készítése Mérési segédlet Informatika 2 A labor feladat célja, hogy a hallgatót megismertesse a TCP/IP protokollt használó programok készítésével. Ezen belül bemutatásra kerül a Berkley Socket API, amelynek segítségével lehetővé válik a hálózati kommunikáció implementálása Linux/Unix és MS Windows rendszereken. A labor elvégzéséhez szükséges a C programozói tudás! A Berkeley socket API ismertetése A következő fejezetekben a Berkeley socket API használatába tekintünk be. Ennek használatával lehetséges a Linux/Unix és MS Windows rendszereken a hálózati kommunikáció implementálása. A socket A socket az applikációk közötti kommunikációt lehetővé tévő kétirányú kapcsolat elnevezéseként értelmezhető. Tulajdonképpen egy SOCKET típusú leíró 1, amelyet létre kell hoznunk, majd az egyes rendszerhívásoknál ezzel hivatkozhatunk az adott kommunikációs csatornára. Új socketeket a socket() rendszerhívással hozhatunk létre. Létrehozáskor a sockethez egy protokollt rendelünk, amelyet az majd használni fog. Azonban ebben az állapotban a socket még nem kapcsolódik sehova, ezért kommunikációra még nem használható. SOCKET socket(int domain, int type, int protocol); A függvény 0-nál kisebb értékkel tér vissza hiba esetén. Ha sikeres, akkor egy socket leíróval, amely 0 vagy nagyobb érték. A három paraméter a használandó protokollt definiálja. Az első (domain) megadja a protokoll családot. A következő táblázat néhány lehetséges értékét tartalmazza. Protokoll PF_UNIX, PF_LOCAL PF_INET PF_INET6 Jelentés Unix domain (gépen belüli kommunikáció) IPv4 protokoll IPv6 protokoll A következő paraméter (type) kiválasztja a protokoll családon belül a kommunikáció típusát. Lehetséges értékei az alábbiak: 1 Linux alatt: int típusú 1

Típus SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET SOCK_RAW SOCK_RDM Jelentés Sorrendtartó, megbízható, kétirányú, kapcsolatalapú bájtfolyam-kommunikációt valósít meg. Datagramalapú (kapcsolatmentes, nem megbízható) kommunikáció. Sorrendtartó, megbízható, kétirányú, kapcsolatalapú kommunikációs vonal, fix méretű datagramok számára. Nyers hálózati protokoll hozzáférést tesz lehetővé. Megbízható datagramalapú kommunikációs réteg. (Nem sorrendtartó.) A harmadik paraméter (protocol) a protokoll család kiválasztott típusán belül választ ki egy protokollt. Mivel egy protokoll családon belül egy kommunikáció típust többnyire csak egy protokoll implementál, ezért a tipikus értéke: 0 Példa Az alábbi példa egy TCP socketet hoz létre: SOCKET sock; if((sock = socket(pf_inet, SOCK_STREAM, 0)) < 0) perror("socket"); A kapcsolat felépítése Ha összeköttetés-alapú kommunikációt szeretnénk folytatni egy kliens és egy szerver program között, akkor ehhez stream jelegű socketet kell létrehoznunk. Azonban ez önmagában nem elegendő a kommunikációhoz. Össze kell kapcsolnunk a két fél socketét, hogy adatokat vihessünk át rajta. Ennek a kapcsolat felépítésnek a részleteit a következő ábrán láthatjuk. Kliens Szerver socket() socket() bind() listen() connect() accept() Kapcsolat létrejött 1. ábra A socket kapcsolat felépítése 2

Az ábrán a kliens és a szerver oldalon egymás után meghívandó függvények láthatóak. Elsőre látható, hogy a kapcsolat felépítési mechanizmus aszimmetrikus. A szerver oldalon a feladat, hogy egy bizonyos címen várja a program a kapcsolódási igényeket, majd amikor ezek befutnak, akkor kiépítse a kapcsolatot. A kliens oldalon ezzel szemben a feladat azl, hogy a szerver címére kapcsolódási kérést küldjünk, amelyre az reagálhat. Ezen feladatok végrehajtását tekintsük át lépésenként. Szerver: 1. A szerver oldalon létre kell hoznunk egy socketet, amelyet a későbbiek során szerver socketként fogunk használni. A szerver socket kommunikációra nem alkalmas, csak kapcsolatok fogadására. 2. Össze kell állítanunk egy cím struktúrát, amelyben leírjuk, hogy a szerver hol várja a kapcsolódásokat. 3. Az előbbi lépésben összeállított címhez hozzá kell kötnünk a socketet. 4. Be kell kapcsolnunk a szerver-socket módot, vagyis hogy a socket várja a kapcsolódásokat. 5. Fogadnunk kell az egyes kapcsolódásokat. Ennek során minden kapcsolathoz létrejön egy kliens socket, amely az adott féllel való kommunikációra használható. Kliens: 1. A kliens oldalon is létre kell hoznunk socketet. Ezt az előző esettől eltérően kliens-socketként, a kommunikációra fogjuk használni. 2. Össze kell állítanunk egy cím struktúrát, amelyben leírjuk, hogy a szerver milyen címen érhető el. 3. Kapcsolódnunk kell a szerverhez. Amikor ez a kapcsolat létrejött, akkor a továbbiakban a socket képes továbbítani az adatokat. A következőkben áttekintjük, hogy az egyes lépések milyen függvények segítségével valósítható meg. Azonban mivel a feladat szerver készítése, ezért a szerver lépéseire koncentrálunk első sorban. Cím összeállítása Mielőtt a cím összeállításra rátérnénk meg kell vizsgálnunk egy problémát. A címek összeállítása során több bájtos adattípusokat használunk (pl.: IPv4 cím 4 bájtos long, a port szám 2 bájtos short). Azonban az egyes processzorok különböző módon tárolják az egyes adattípusokat. Két tárolási mód terjedt el: a big endian, amely a magasabb helyi értékű bájttal kezdi a tárolást, illetve ennek ellentéte a little endian. Big endian architektúra például a Sun Sparc, little endian pedig az Intel x86. Azonban a hálózaton ezeknek a különböző architektúráknak is meg kell érteniük egymást, ezért közös adatábrázolásra van szükség. Ezt nevezzük hálózati bájt-sorrendnek, amely a big endian ábrázolást követi. Az adott architektúrán használt ábrázolást pedig hoszt bájt-sorrendnek. A két ábrázolás közötti váltásokat a következő függvények végzik: Függvény Jelentés ntohs Egy 16-bites számot a hálózati bájt-sorrendből a hoszt bájt-sorrend sorrendjébe vált át. ntohl Egy 32-bites számot a hálózati bájt-sorrendből a 3

htons htonl hoszt bájt-sorrendjébe vált át. Egy 16-bites számot a hoszt bájt-sorrendjéből hálózati bájt-sorrendbe vált át. Egy 32-bites számot a gép bájt-sorrendjéből hálózati hoszt bájt-sorrendbe vált át. Azokon az architektúrákon, ahol szükséges a konverzió ezek a függvények megfordítják a bájt-sorrendet, ahol pedig nem, ott csak visszaadják a paraméter értékét. A címábrázoláshoz a socket API a következő általános struktúrát alkalmazza: struct sockaddr unsigned short sa_family; /* címcsalád, AF_xxx */ char sa_data[14]; /* 14 bájtos protokoll cím */ ; A címet használó függvények paraméterként ilyen típust várnak. Azonban egyes protokollokhoz létezik ennek specializált változata is, amely az adott protokoll esetén könnyebben használható. IPv4 esetén ez a következő képen néz ki: struct sockaddr_in unsigned short int sin_family; /* Címcsalád = AF_INET */ unsigned short int sin_port; /* A port száma */ struct in_addr sin_addr; /* IP cím */ unsigned char sin_zero[8]; /* struct sockaddr vége */ ; Ezen belül az in_addr struktúra az alábbi: struct in_addr unsigned long int s_addr; Ebben helyezhetjük el a cím egyes bájtjait. Ne feledjük, hogy mind a címnek, mind a portnak hálózati bájtsorrendűnek kell lennie, ezért a korábban látott htonl() illetve htons() függvényeket kell használnunk a konverziójukhoz. A szerver esetén a cím beállításnál valójában csak a portot kell megadnunk, míg a címre használhatjuk az INADDR_ANY makrót. Ez valójában a 0.0.0.0 címet jelenti, amely azt mondja meg, hogy minden hálózati interfész adott portján várjuk a kapcsolódást. Példa Az alábbiakban két példát láthatunk a cím összeállítására. Az első példában egy szerver számára állítjuk össze a címhez kötéshez a cím struktúrát. A példában a szerver a számítógép össze hálózati interfészén az 1234-es porton lesz majd elérhető: sockaddr_in addr; 4

addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(1234); A másik példa azt mutatja meg, hogy hogyan állíthatjuk össze a kliensben a címstruktúrát, amiben a szerver címe szerepel. A szerver IP címe esetünkben 192.168.0.1 és portja 1234 lesz: sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("192.168.0.1"); addr.sin_port = htons(1234); A socket címhez kötése Az előző lépésben összeállított címet hozzá kell rendelnünk a sockethez. Ezt a műveletet kötésnek nevezzük, és a következő rendszerhívással lehet végre hajtani: int bind(socket sock, struct sockaddr *my_addr, socklen_t addrlen); Az első paraméter a socket leírója, a második a címet leíró struktúra, az utolsó a címet leíró struktúra hossza. A visszatérési érték sikeres végrehajtás esetén 0, egyébként pedig mínusz érték. Példa Az alábbi példában a korábban összeállított címmel hajtjuk végre a címhez kötés műveletét: if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) perror("bind"); A szerver mód bekapcsolása A címhez kötés után a socketet szerver módba kapcsolhatjuk. Ez után már kapcsolódhatunk hozzá klienssel. A szerver módba kapcsolást a következő rendszerhívással végezhetjük el: int listen(socket sock, int backlog); Az első paraméter a socket leírója. A második paraméter, a backlog megadja, hogy hány kapcsolódni kívánó socket kérelme után utasítsa vissza az újakat. Ebbe csak azok a kapcsolódó socketek számítanak bele, amelyeket még nem fogadott a szerver. A visszatérési érték sikeres végrehajtás esetén 0, egyébként pedig mínusz érték. 5

Példa A korábban már címhez kötött socketet az alábbi módon kapcsolhatjuk szerversocket módba: if(listen(sock, 5) < 0) perror("listen"); Kliensek kapcsolódásának fogadása A kliensek kapcsolódását a következő rendszerhívás fogadja: SOCKET accept(socket sock, struct sockaddr *addr, socklen_t *addrlen); Az első paraméter a szerver socket leírója. Az addr és addrlen paraméterekben a másik oldal címét kapjuk meg. Az addrlen egy integer szám, amely megadja az addr változó méretét. Amennyiben nem vagyunk kíváncsiak a csatlakozó kliens címére, akkor az addr és addrlen paramétereknek megadhatunk NULL értéket. A függvény visszatérési értéke az új kapcsolat leírója, egy kliens socket. A későbbiekben ezt használhatjuk a kommunikációhoz. Ha a visszatérési érték 0-nál kisebb, akkor hibát jelez. Kapcsolódás a szerverhez A kliens oldalon a cím összeállítása után kapcsolódnunk kell a szerverhez. Ezt a következő rendszerhívással tehetjük meg: int connect(socket sock, struct sockaddr *addr, socklen_t addrlen); Az első paraméter a kliens socket leírója. Az addr és addrlen paraméterekben a szerver címét adjuk meg. Az addr paraméter tartalmazza a címet, míg az addrlen az addr paraméterben átadott cím méretét kell, hogy megadja. A függvény 0 értékkel jelzi a sikeres végrehajtást, míg mínusz értékkel a hibát. Példa A korábbi példában összeállított szerver címre a kapcsolódást az alábbi példa mutatja be: if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) perror("connect"); 6

Adatok küldése és fogadása A kliens és a szerver program összekapcsolt kliens socketét egy kétirányú csővezetéknek tekinthetjük, amelyen bájtokat küldhetünk és fogadhatunk. Az adatok küldésére a következő rendszerhívást használhatjuk: int send(socket s, const void *msg, size_t len, int flags); Az első argumentum a socket leírója, a második az elküldendő adat pufferére mutató pointer, a harmadik az elküldendő adat mérete. A flags paraméter a kommunikáció jellegét módosító beállításokat tartalmazhat. A gyakorlat keretein belül használjuk a 0 értéket. A függvény visszatérési értéke tartalmazza az elküldött bájtok számát. A mínusz érték a hibát jelzi. Adatokat a recv() rendszerhívással fogadhatunk. Ez a függvény addig nem tér vissza, amíg valamilyen információ nem érkezik. Az alakja a következő: int recv(socket s, void *buf, size_t len, int flags); Az első paraméter itt is a kliens socket leírója, a második a fogadó puffer mutatója, a harmadik pedig a puffer mérete. A flags paraméter itt is a kommunikáció jellegét módosító beállításokat tartalmazhat, azonban jelenleg használjuk a 0 értéket. A függvény visszatérési értéke a beolvasott bájtok számát tartalmazza. Ez kisebb vagy egyenlő azzal, amit mi puffer méretnek megadtunk. Figyeljünk arra, hogy a puffer tartalmából csak annyi bájt a hasznos információ, amennyit ez a visszatérési érték megad. Ha a visszatérési érték 0, akkor az azt jelzi, hogy a kapcsolat lezárult. Ebben az esetben befejeződött a kommunikáció és le kell zárnunk a socketet. Ha a visszatérési érték mínusz szám, akkor az hibát jelez. A kapcsolat lezárása A kapcsolatot a következő rendszerhívással zárhatjuk le 2 : int closesocket(socket s); A paraméter a socket leírója. A visszatérési érték sikeres végrehajtás esetén 0, egyébként pedig mínusz érték. Ellenőrző kérdések 1. Mi a különbség a szerver és a kliens socket között? 2. A cím összeállításánál miért szükséges a számokat konvertálni? 3. Miért szükséges a szerver socketet címhez kötni és miért nem kell a kliens socketet? 4. Az accept() függvény meghívásakor mi történik, ha éppen nincs bejövő kapcsolat? 5. A kommunikációs kapcsolatot hogyan zárhatja le a kliens, illetve a szerver oldal? 2 Linux alatt: int close(int s); 7

6. Írjon C nyelvű kódrészletet, amely az s leíróval reprezentált kliens socketből képes 16 byte adat fogadására! 7. Írjon C nyelvű kódrészletet, amely az s leíróval reprezentált kliens socketen keresztül elküldi a hello stringet! 8. Írjon C nyelvű kódrészletet, amely megvizsgálja, hogy az str1 és str2 nevű karakter tömbök tartalma megegyezik-e! 9. Írjon C nyelvű kódrészletet, amely megvizsgálja, hogy az str1 nevű karakter tömb tartalmazza-e az str2 nevű karakter tömb értékét! 10. Írjon C nyelvű kódrészletet, amely megvizsgálja, hogy az str1 nevű karakter tömb tartalmazza-e a ch nevű karaktert! A feladat A gyakorlat során a hallgató feladata, hogy elkészítsen egy TCP szerver applikációt C nyelven, amely a következőket teljesíti: Egy paraméterként megadott TCP porton fogadja a kliensek kapcsolódásait! Vagyis megvalósítja azokat a funkciókat, amelyeket a szerver esetén a segédlet leír. Egy kapcsolat fogadása után elegendő, ha csak az adott klienssel foglalkozik. Azonban amikor lezárul a kapcsolat, akkor fogadja új kliens kapcsolódását! A klienssel való kommunikáció során elvégzendő műveleteket a gyakorlatvezető ismerteti! 8

Függelék A MS Windows segítség Az MS Windows alatti fejlesztést MS Visual Studio program használatával végezzük. A project létrehozásakor célszerű az üres C++ alkalmazás választani kiindulási pontnak. A program lefordítása és futtatása Az elkészült program lefordításához szükséges a ws2_32.lib könyvtár állomány használata, mert különben a hálózatkezelő függvényeink implementációját a linker nem találja meg. Vagyis a project beállításainál a linkelés parancssorához vegyük hozzá a ws2_32.lib állományt. A programot paraméterezve kell futtatnunk. Ennek legegyszerűbb módja, ha nyitunk egy parancsterminált (cmd.exe). Megkeressük a lefordított exe állományt és lefuttatjuk. Paraméterként meg kell adnunk a port számát. A szerver kipróbálása Az elkészült TCP szerver programot a telnet program segítségével próbálhatjuk ki, amely egy TCP kliens. A telnet program használatához egy command prompt-ot kell nyitnunk. Ezt kétféle módon tehetjük. A Start / Programs / Accessories / Command Prompt menüpont segítségével, vagy a Start / Run menüpont kiválasztásával és a cmd parancs lefuttatásával. A command prompt ablakban kell kiadnunk a telnet parancsot. Első paraméterként meg kell adnunk a szerver gép nevét, amely lokális futtatás esetén localhost, második paraméterként pedig a szerver portját. Például: telnet localhost 1234 A program jelzi, ha nem sikerül kapcsolódnia a szerverhez. Ha a kapcsolat felépült, akkor a begépelt sorokat elküldi a szerver programnak. A telnet program MS Windows implementációja karakterenként küldi el azt, amit begépeltünk, így a szervernek egyből reagálnia kell minden karakter után. A program váza Az alábbi C (C++) nyelvű programváz segítséget nyújt a fejlesztés elkezdéséhez MS Windows alatt: #include <stdio.h> #include <winsock2.h> int main(int argc, char* argv[]) WSADATA wsd; if(wsastartup(0x0202, &wsd)!= 0) perror("wsastartup"); if(argc < 2)

printf("hasznalat: %s port\n", argv[0]); //TODO WSACleanup(); return 0;

Függelék B Linux segítség A feladat megvalósításához szükség van egy terminál, egy szövegszerkesztő, és a gcc program használatára. Szövegszerkesztőnek a kwrite program használata javasolt, mivel kezelőfelülete egyszerű és rendelkezik szintaxis kiemelő funkcióval. Az alábbiakban ismertetett parancsokat a terminál ablakba kell beírni. A programozói segítség Az egyes rendszerhívásokról és C függvényekről a man parancs segítségével angol nyelvű segítséget érhetünk el. Ennek formája: Rendszerhívások esetén: man 2 rendszerhívás C függvények esetén: man 3 C-függvény A program lefordítása és futtatása Az elkészült forráskódot a gcc parancs segítségével fordíthatjuk le. Ennek paraméterezése a következő: gcc -Wall -o kimenet forrás.c A fordító sikeres fordítás esetén nem ír ki semmit, csak előállítja a futtatható program kódot. Probléma esetén a problémákat három csoportra oszthatjuk: Típus Figyelmeztetés (warning) Fordítási hiba (compiler error) Linker hiba (linker error) Leírás A jelzett sor szintaktikailag nem hibás, de érdemes ellenőrizni, mert elvi hibás lehet. Viszont a program lefordul és használható. A jelzett sor szintaktikailag hibás, vagy valamely korábbi sorban elkövetett hiba hatása. A linker nem találja a hivatkozott kódot. Többnyire függvény név elírások okozzák. A lefordított programot a következő módon lehet futtatni:./program param1 Ez az aktuális könyvtárból lefuttatja a program nevű programot a param1 paraméterrel. A programot leállítani a Ctrl+C billentyű kombinációval lehet. A szerver kipróbálása Az elkészült TCP szerver programot a telnet program segítségével próbálhatjuk ki, amely egy TCP kliens. A telnet programnak első paraméterként meg kell adnunk a

szerver gép nevét, amely lokális futtatás esetén localhost, második paraméterként pedig a szerver portját. Például: telnet localhost 1234 A program jelzi, ha nem sikerül kapcsolódnia a szerverhez. Ha a kapcsolat felépült, akkor a begépelt sorokat elküldi a szerver programnak. Figyeljünk arra, hogy mivel a terminál kanonikus, ezért sorokat fog elküldeni az Enter lenyomása után! A program váza Az alábbi C nyelvű programváz segítséget nyújt a fejlesztés elkezdéséhez Linux alatt: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> int main(int argc, char* argv[]) int ssock; int reuse = 1; if((ssock = socket(pf_inet, SOCK_STREAM, 0)) < 0) perror("socket"); setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); //TODO return 0;