[Grafika] [WebTip] [Fotografování] [Galerie] [MujMac] [Printing]
  Redakce: info (at) builder.cz   Inzerce: reklama (at) grafika.cz
Diskuzní fóra
.Net (58811)
ASP (1464)
ActiveX (163)
Allegro (126)
Assembler (3699)
C++ Builder (21656)
C/C++ (39174)
Databáze (27980)
Delphi (71030)
DelphiX (1575)
DirectX (1427)
Java (34885)
JavaScript (11036)
Matematické programy (1906)
OOP a UML (579)
OpenGL (6612)
Php (61391)
PowerBuilder (457)
Problémy a algoritmy (8579)
Programování v Linuxu (1837)
Právo a programování (3146)
Python (1076)
Ruby (128)
Visual Basic (11529)
Visual C++ (12469)
Wap (56)
Web (10262)
Web servery (5238)
Win32 (12737)
Windows CE (830)
XML/XSL (1655)
Textová inzerce
Služby Builder.cz
  • Bazar - koupím(0)
  • Bazar - prodám(0)
  • Hledám práci(0)
  • Nabízíme práci(0)
  • Projekty(0)
  • Protokol UDP 2.část
    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.
    Sokety a C++
    Předchozí díl: Protokol UDP 1.část

    Následující díl: Zpracování chyb soketů v Linuxu
    Autor: Radim Dostál
    Rubrika: C/C++
    Publikováno: 20.02. 2003
     Tisk článku
    Poslat odkaz emailem
     

    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.


    Zpět na začátek stránky

    Autor: Radim Dostál
    Klikni pro další články autora

    Hodnocení článku
    1 | 2 | 3 | 4 | 5
    Aktuální známka: 2.59
    (Počet známek: 3643)

    Komentáře k článku
    Jan Strrnad07.08.11:12udp scaner
    Michal Linhart20.02.20:48MX záznamy
    Radim Dostál27.02.12:42RE: MX záznamy
         





    info@builder.cz
    Vydává Grafika Publishing, s.r.o.
    Copyright (c) 1997-2002 Všechna práva vyhrazena