Portál AbcLinuxu, 10. května 2024 08:46


Dotaz: UDP klient, funkce read

20.4.2011 15:04 Michal
UDP klient, funkce read
Přečteno: 216×
Odpovědět | Admin
Ahoj, dělám klienta, který má pomocí UDP stáhnout ze serveru soubor. Server posílá data po 265B paketech (9B hlavička, 256B data). Všude se píše, že s UDP se používá dvojice recvfrom a sendto. Ale mě se nelíbilo, že se jim musí předávat další struktura s informacemi o druhé straně.

Někde jsem si přečetl, že se dají normálně použít i funkce read a write stejně jako při komunikaci skrz TCP. Rozhodl jsem se, že to tedy udělám tak.

Připojení:

    unsigned int       inaddr;
    struct hostent     *ph;
    struct sockaddr_in my_addr;

    if ((inaddr = inet_addr(addr))!=INADDR_NONE)
        ph=gethostbyaddr((char *)&inaddr, sizeof(unsigned int), AF_INET);
    else  ph=gethostbyname(addr);

    if (ph) {
        cout << "Connecting to " << ph->h_name << endl;
    }
    else {
        cerr << "Unable to connect " << ph->h_name << ", not in name list." << endl;
        return false;
    }

    if ((m_iSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP))<0) {
        cerr << "Can not open socket." << endl;
        return false;
    }

    bzero((char *) &my_addr, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_addr.s_addr = INADDR_ANY;
    my_addr.sin_port = htons(4000);

    if (connect(m_iSocket,  (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) {
        cerr << "Can\'t connect." << endl;
        close(m_iSocket);
        return false;
    }

Potom server nějak (nevím jak, mám jen binárku) odesílá data a já je v klientovi přijímám takto:


...
struct Message {
    long    id;
    unsigned short   seq;
    unsigned short   ack;
    char    flag;
    char    data[256];
};
...
    Message buf;
    for (int i = 0; i < 256; i++) {
        buf.data[i] = m_mRecMsg.data[i] = 0;
    }

    int ret = read(m_iSocket, (void *)&buf, sizeof(buf));
    cout << "Pocet prijatych bajtu: " << dec << ret << " z " << sizeof(buf) << endl;
    if (ret < 0) {
        cerr << "Error reading from socket." << errno << endl;
        return false;
    }
    m_iLastRecvDataLength = ret - sizeof(long) - 2*sizeof(short) - 1;

    if (m_iLastRecvDataLength > 0) {
        strncpy(m_mRecMsg.data, buf.data, m_iLastRecvDataLength);
    }
    m_mRecMsg.ack = ntohs(buf.ack);
    m_mRecMsg.flag = buf.flag;
    m_mRecMsg.id = ntohl(buf.id);
    m_mRecMsg.seq = ntohs(buf.seq);

    printMsg(m_mRecMsg);

    return true;

Je to výňatek z programu, ale pro ilustraci by to mělo snad stačit. Problém je v tom, že server odešle 256B dat + 9B hlavičku, klient by je měl tedy přijmout. návratová hodnota z read dokonce potvrzuje, že přijala 265B dat. Ale přesto jsou data neúplná. V poli data je někdy jen určitý počet (asi tak 100-150) platných bajtů a zbytek jsou nuly. Vypadá to například takhle:

server:
F1EA0006  SEND  127.0.0.1:41229  seq=18176 ack=0 flags=00 data(256): 5b 7b 15 f6 8d 00 41 80 ... 6f 73 a6 73 60 60 77 7a
klient: 
Pocet prijatych bajtu: 265 z 268
Prijata: f1ea0006	0	18176	0	data(256):5b 7b 15 f6 8d ... 0 0 0 0 0 0 0 0 0 0 

Může za to read? Nebo mám něco principiálně špatně? Vím, že u TCP se muselo číst po bajtech, ale UDP se snad nesmí ne?

Budu moc vděčný za každou radu, už se s tím morduju 2 dny.
Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

20.4.2011 16:49 Michal
Rozbalit Rozbalit vše Re: UDP klient, funkce read
Odpovědět | | Sbalit | Link | Blokovat | Admin
Jenom doplním, že píšu v C++ pod Linuxem.
20.4.2011 17:54 Sten
Rozbalit Rozbalit vše Re: UDP klient, funkce read
Odpovědět | | Sbalit | Link | Blokovat | Admin
sendto a recvfrom se používají, jenom pokud nepoužijete connect, jinak můžete klidně používat send a recv, resp. jejich ekvivalenty write a read.

Chyba bude v použití strncpy, to totiž skončí na prvním null bajtu. Použijte memcpy. Případně raději použijte nějaký postup z C++.
20.4.2011 19:35 Michal
Rozbalit Rozbalit vše Re: UDP klient, funkce read
Máte pravdu, nenapadlo mě, že se mezi daty může objevit i \0 i když teď je mi to už jasný :-). Mockrát děkuji.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.