c - hálózat programozása

 ( BimbaLaszlo | 2011. január 2., vasárnap - 16:44 )

Üdv!

Szeretnék egy weboldalt elérni a glibc gethostbyname függvényének segítségével a programomon belül, windows / mingw alatt. A kód a 'programozás c nyelven' című könyvből vett példa módosított változata:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <winsock2.h>

#define PROGRAM_NAME "foo"

int
main( int argc, char *argv[] )
{
    int
        n       = 0;

    struct hostent
        *host   = NULL;

    if( argc < 2 )
    {
        fprintf(stderr, "usage:\n  " PROGRAM_NAME " \n");
        exit( 1 );
    }

    if( (host = gethostbyname( argv[1] )) == NULL )
    {
        fprintf( stderr, PROGRAM_NAME ": %s\n", strerror( h_errno ) );
        exit( 1 );
    }

    printf( "%s\n", host->h_name );

    for( n = 0 ; host->h_aliases[ n ]   != NULL ; ++n )
        printf( "%s\n", host->h_aliases[ n ] );

    for( n = 0 ; host->h_addr_list[ n ] != NULL ; ++n )
        printf( "%hhu.%hhu.%hhu.%hhu\n",
                host->h_addr_list[n][0],
                host->h_addr_list[n][1],
                host->h_addr_list[n][2],
                host->h_addr_list[n][3]
        );

    return( 0 );
}

A fordítást a következő paraméterekkel végeztem:

gcc foo.c -o foo.exe -Wall -lws2_32

Viszont mikor futtatom a progit, akkor 'Unknown error' üzenettel lép ki ha például a 'google.com' argumentumot használom, de a 'localhost' esetén is (xampp szerver). Néztem wireshark-ban, hogy egyáltalán küld-e kérést, de sajnos nem. Tűzfal ki volt kapcsolva, egyéb hálózatot használó program sem futott (tudtommal), tehát nem értem, hogy miért nem működik. Linux alatt (persze más include-okkal) működött, de hogy mi baja a windows-zal, arra már tippem sincs és a google sem tudott segíteni, ezért fordultam hozzátok segítségért.

Megoldás:

Winsock 2.0 használata esetén a következő kódrészletet kell beilleszteni a socket használata elé:

WSADATA
    wsaData;

if( WSAStartup( MAKEWORD( 2,0 ), &wsaData ) != 0 )
{
    fprintf( stderr, PROGRAM_NAME ": wsastartup failed\n" );
    exit( 1 );
}

Majd ha már nem akarjuk a socket-eket tovább használni, akkor a WSACleanup() függvénnyel zárjuk a kódot.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

A h_errno szerintem nem dekódolható az strerror-ral.
Erre UNIX-on a hstrerror/herror való. Bár van szumma kb. 4 hibakód, ami ott lehetséges...

Jogos - bár glibc manuáljában nem találtam a hstrerror függvényt, mindenesetre módosítottam a progit, de így is ismeretlen a hiba forrása, a hibakód: 10093
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.

Egyébként (látom, megtaláltad a hibát, de erre rá tudtál volna jönni önerőből) a 10093 windows-os hibakód, és ha rákeresel a guglival, hamar meg is találod:

WSANOTINITIALISED
10093
Successful WSAStartup not yet performed.

Either the application has not called WSAStartup or WSAStartup failed. The application may be accessing a socket that the current active task does not own (that is, trying to share a socket between tasks), or WSACleanup has been called too many times.

Jogos, kerestem is google-ban, hogy mi lehet ez az error code, és asszem ezt meg is találtam, csak nem értettem, mert azt hittem, hogy a WSAStartup egy program, nem pedig függvény... (-_-')
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.

Beej's guide
Nézd meg a linket, windowson kelleni fog a WsaStartup függvény meghívása szerintem.

Megvan a megoldás. Köszi szépen!
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.

Egy "#ifdef WIN32" -vel bastyazd korbe.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Az előfeldolgozó logikáját nem igazán értem, mert az

#ifdef WIN32
    #include <winsock2.h>
#else
    #include <netdb.h>
#endif

sorokra a

fatal error: netdb.h: No such file or directory

választ adja. Pedig WIN32 definiálva van, ki is próbáltam:

#ifdef WIN32
    printf( "win" );
#else
    printf( "nem win" );
#endif

Persze a kimeneten a "win" jelent meg. Azt nem értem, hogy ha az előfeldolgozó a feltétel kiértékelése után a WIN32 ágat követi, akkor miért hiányolja azokat a fájlokat, amikhez most épp semmi köze nem lenne?
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.

Furi, nekem jo szokik lenni. Kene egy gcc -v kimenet.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal

Úgy néz ki megvan a hiba: ha az -ansi kapcsolóval fordítom, akkor írja ezt a hibát és félbeszakad a fordítás, -ansi nélkül viszont még csak nem is figyelmeztet a fájlhiányra. Mindenesetre itt a -v kimenete:

ansival: http://www.diffpaste.com/#/859/
ansi nélkül: http://www.diffpaste.com/#/860/

Ismételten jelzem, hogy mingw környezetről van szó! Az -ansi valahogy nem egészen ugyanaz, mint Linux alatt, mert például nem szabványba illő szintaxisra ott figyelmeztet (pl.: változó deklarálása előtt nem hívhatnánk függvényeket), itt viszont nem.
--
Azt akarom, hogy az emberek ne kényszerből tanuljanak, hanem azért, mert tudni akarnak.

Teljesen eltunyultam mióta Java-ban, PERL-ben, C#-ban meg QT-ben programozom.
5 éve nem csináltam ilyen #ifdef-es matyóhímzést a kódba.

Lehet, hogy újra kellene valami jó kis C-s cuccot írni, mert teljesen ki fogok jönni a gyakorlatból.

:)

Nekünk sajnos néha a Qt-ba is kell ifdef :)

Van valami gyűjtemény ilyen trükkökkel kapcsolatban egyébként?
Nem nagyon tudom, hogy pontosan milyen definiált értékekre lehet hivatkozni pl. windowson vagy linuxon, ami biztosan definiálva is van pl. minden linux disztribúcióban.

s

[feliratkozás]