Protokol UDP 2.část - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Protokol UDP 2.část

cpp net

20. února 2003, 00.00 | Dnes dokončíme téma UDP. Neuvedeme si žádnou novou funkci. Pouze se podíváme, že i na datagramový soket je možné zavolat funkci connect. Článek je opět věnován operačnímu systému Linux i operačnímu systému MS Windows. Na konci článku jsou ke stažení 2 příklady.

V minulém článku jsme si pověděli základní informace o UDP a srovnali UDP s TCP, který jsme již znali z dřívějších článků. Několikrát jsem upozornil, že při použití protokolu UDP nenavazujeme spojení. Nejedná se o spojovou službu. Přesto na datagramový soket lze zavolat funkci connect. Nenavážeme s ní spojení. Její význam je trochu jiný.

V minulém díle jsme používali pro příjem a odeslání dat funkce sendto a recvfrom. Tyto funkce nám umožnili jedním soketem odesílat a přijímat data kamkoliv a odkudkoliv (nebyli jsme vázání jednou adresou). Takové požadavky na jeden soket ale většinou nemáme. Většinou vytváříme soket, pomocí kterého chceme odesílat data na jedno místo (resp. je z jednoho místa přijímat). V každém případě je časté, že funkce sendto a recvfrom používáme několikrát za sebou se stejnými parametry udávajícími adresu. Bylo by asi nepohodlné ji pořád psát (nebo dokonce strukturu několikrát plnit stejnými daty). Bylo by ideální, kdyby jsme mohli nějak operačnímu systému říci, že tímto datagramovým soketem budeme komunikovat jen se zadanou IP adresou a UDP portem. Ať si ji zapamatuje a nechce ji po nás při každém odesíláni, resp. přijímání dat. Až budeme chtít komunikovat s jinou IP adresou a UDP portem, dáme operačnímu systému vědět. Jak vás asi napadlo, právě k těmto účelům u datagramových soketů slouží funkce connect. Touto funkcí nenavážeme spojení, tak jak jsme to dělali u protokolu TCP. Funkcí connect zavolanou na datagramový soket pouze oznámíme operačnímu systému, že tento soket nějakou dobu bude komunikovat se zadanou IP adresou a UDP portem (daný instancí struktury sockaddr_in). Tím pádem je zbytečné, aby jsme při odesílání (resp. při přijímání) dat tímto soketem museli neustále zadávat kam (resp. odkud) data posíláme (přijímáme). Proto nemusíme používat sendto a recvfrom, ale můžeme použít send a recv. Funkce sendto se od send liší pouze v tom, že udáváme také adresu a port příjemce. Budeme-li chtít změnit adresu a port druhé strany, jednoduše znovu zavoláme connect s novými hodnotami.

Díky toho můžeme používat v podstatě stejné funkce pro naprosto odlišné protokoly jakými jsou UDP a TCP. Podívejme se na použití connect a následné použití send a recv u UDP protokolu. Uvedeme si UDP klienta v Linuxu Na základě tohoto zdrojového textu je snadné vytvořit UDP klienta v MS Windows®. Navíc jsou na závěr článku oba příklady ke stažení.

UDP klient v Linuxu
#include <iostream>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <netdb.h>

#define BUFSIZE 1000

using namespace std;

int main(int argc, char *argv[])
{
   hostent *host;                        // Vzdálený počítač
    sockaddr_in serverSock;              // Vzdálený "konec potrubí"
    int mySocket;                        // Soket
    int port;                            // číslo portu
    char buf[BUFSIZE];                   // Přijímací buffer
    int size;                            // Počet přijatých a odeslaných bytů
    socklen_t addrlen;                   // Velikost adresy
    
    if (argc != 3)
    {
        cerr << "Syntaxe:\n\t" << argv[0]
             << " " << "adresa port" << endl;
        return -1;
    }
    port = atoi(argv[2]);
    // Zjistíme info o vzdáleném počítači
    if ((host = gethostbyname(argv[1])) == NULL)
    {
        cerr << "Špatná adresa" << endl;
        return -1;
    }
    // Vytvoříme soket
    if ((mySocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        cerr << "Nelze vytvořit soket" << endl;
        return -1;
    }
    // Zaplníme strukturu sockaddr_in
    // 1) Rodina protokolů
    serverSock.sin_family = AF_INET;
    // 2) číslo portu, ke kterému se připojíme
    serverSock.sin_port = htons(port);
    // 3) Nastavení IP adresy, ke které se připojíme
    memcpy(&(serverSock.sin_addr), host->h_addr, host->h_length);
    
    if (connect(mySocket, (sockaddr*)&serverSock, sizeof(serverSock)) == -1)
    {
      cerr << "Problém s přiřazením cílové adresy soketu" << endl;
      return -1;
    }
    
    for (register int i = 0; i < 5; i++)
    {
        char temp[30];
        // Odeslání dat
        sprintf(temp,Datagram číslo "%d\n",i);
        if ((size = send(mySocket, temp, strlen(temp), 0))  == -1)
        {
                cerr << "Problém s odesláním dat" << endl;
                return -1;
        }
        cout << "Odesláno " << size << endl;
        // Příjem dat
        if ((size = recv(mySocket, buf, BUFSIZE, 0)) == -1)
        {       
                cerr << "Problém s přijetím dat" << endl;
                return -1;
        }
        cout << "Přijato " << size << endl;
        buf[size] = '\0';
        cout << buf << endl;
    }
    close(mySocket);
    return 0;
}

Příklady ke stažení

Tyto příklady lze v komunikaci libovolně kombinovat s příklady z minulého dílu. Můžete si vyzkoušet, že UDP klientem se na TCP server nepřipojíte a naopak. Také si všimněte, že příklady z tohoto článku se velice podobají příkladům z článků o TCP protokolu. Zkuste si také spustit na jednom počítači TCP server a UDP server se stejným číslem portu. Porty mají stejné číslo, ale stejné nejsou. V jednom případě se jedná o UDP port, v druhém případě se jedná o TCP port. Takže to bez problému půjde.

Při komunikaci pomocí soketů nemusí vše fungovat tak, jak by jsme si představovali. Při práci se sokety mohou nastat chyby (nelze odeslat data, nelze navázat spojení atd...). Bylo by dobré tyto chyby umět identifikovat a umět pracovat s nimi. Způsob identifikace chyb se v Unixových systémech a v MS Windows® liší. Proto příště opět dočasně rozdělíme seriál na články pro MS Windows® a pro Linux®. Bude to takové oddechové téma (pro někoho možná zbytečné), ale měli by jsme se na něj podívat. Tím budeme mít za sebou základy práce s TCP a UDP pomocí soketů v blokovacím režimu. Pak se budeme moci vydat dále.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: