IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Tutoriel sockets RAW sous windows : prblm de compil


Sujet :

Réseau C

  1. #1
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut Tutoriel sockets RAW sous windows : prblm de compil
    Bonjour à tous,

    je viens vous solliciter car je m'arrache les cheveux depuis quelques jours avec le tutoriel "La programmation des sockets bruts sous Windows".

    Je fais du dev sous Unix depuis 4~5 ans en C/Pro*C. Mais il n'y a rien de bien méchant. C'est du batch assez basique.

    Je souhaite compléter mes compétences et la programmation de sockets m'intéresse beaucoup.
    Après avoir fait qques tests concluants avec les sockets standards, j'essaye de passer aux sockets Raw.

    J'ai repris les sources du tutoriel en question et je bute sur le problème suivant :
    Une erreur à la compilation avec le header WinNT.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: syntax error before '{' token
    Voici la partie de code qui gène. Le message d'erreur pointe la ligne contenant "__asm"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    __inline ULONGLONG
    NTAPI
    Int64ShllMod32 (
        ULONGLONG Value,
        DWORD ShiftCount
        )
    {
        __asm    {
            mov     ecx, ShiftCount
            mov     eax, dword ptr [Value]
            mov     edx, dword ptr [Value+4]
            shld    edx, eax, cl
            shl     eax, cl
        }
    }
    J'utilise Code::Blocks comme IDE et j'ai essayé de compiler avec VC++ ainsi que GNU GCC.

    Merci d'avance pour votre aide.

  2. #2
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    C'est bizarre. C'est sûrement du à une mauvaise configuration de ton environnement. Essaie un peu de compiler en ligne de commandes. Avec gcc c'est très simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc fichier.c -lws2_32 -o mon_appli.exe
    Avec VC (ici c'est VC8, modifie juste les noms de répertoires si tu utilises une version différente), c'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cl fichier.c /I "C:\Program Files\Microsoft Visual Studio 8\VC\include" /I "C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include" /link ws2_32.lib /libpath:"C:\Program Files\Microsoft Visual Studio 8\VC\lib" /libpath:"C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Lib"
    Sous VC6, il n'y a pas de répertoire PlatformSDK.

    Dans tous les cas, il faut que les répertoires où se trouvent les composants exécutables du compilateur soit renseigné dans la variable path, sinon tu dois lancer la commande en étant dans ce répertoire (ce qui requiert que fichier.c s'y trouve aussi, à moins que tu donnes le chemin complet au lieu d'un chemin relatif). Avec MinGW, il s'agit de MinGW > Bin et avec VC, VC > Bin et Common > IDE. Toujours avec VC, la ligne de commande sera beaucoup plus simplifiée si tu utilises le programme Visual Studio Command Prompt (normalement installé avec Visual Studio si tu as installé les "Outils" (VS Tools)).

    Qu'est-ce que ça a donné. Sois précis dans les réponses.

  3. #3
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Alors, pour simplifier la compilation en ligne de commande, j'ai regroupé les sources sous un seul fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    #include <stdio.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdlib.h>
     
    #define MAX_MESSAGE 100
    #define IP_SOURCE "127.0.0.1"
    #define IP_DEST "127.0.0.1"
    #define PORT_SOURCE 5050
    #define PORT_DEST 5050
     
    typedef struct ipheader {
        UCHAR  hlen : 4, version : 4;
        UCHAR  tos;
        USHORT tot_len;
        USHORT id;
        USHORT offset : 13, flags : 3;
        UCHAR  ttl;
        UCHAR  protocole;
        USHORT somme;
        ULONG  ip_source;
        ULONG  ip_dest;
    } IPHEADER;
     
    typedef struct udpheader {
        USHORT port_source;
        USHORT port_dest;
        USHORT tot_len;
        USHORT somme;
    } UDPHEADER;
     
    USHORT checksum(void * lpData, size_t size);
     
    int main()
    {
        WSADATA wsaData;
     
        if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
            fprintf(stderr, "La fonction WSAStartup a echoue.\n");
        else
        {
            SOCKET s;
     
            s = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
            if (s == INVALID_SOCKET)
                fprintf(stderr, "La fonction socket a echoue.\n");
            else
            {
                DWORD sockopt = TRUE;
     
                if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&sockopt, sizeof(sockopt)) == SOCKET_ERROR)
                    fprintf(stderr, "La fonction setsockopt a echoue.\n");
                else
                {
                    char message[MAX_MESSAGE] = "Bonjour.", * buf;
                    USHORT message_len, udp_len, ip_len;
     
                    message_len  = (USHORT)(strlen(message) + 1); /* Longueur du message */
                    udp_len      = (USHORT)(sizeof(UDPHEADER) + message_len); /* Longueur du paquet UDP */
                    ip_len       = (USHORT)(sizeof(IPHEADER) + udp_len); /* Longueur du paquet IP */
     
                    buf = malloc(ip_len);
                    if (buf == NULL)
                        fprintf(stderr, "La fonction malloc a echoue.\n");
                    else
                    {
                        SOCKADDR_IN dest;
                        IPHEADER ip;
                        UDPHEADER udp;
     
                        /* Remplissage de la structure ip (en-tete du paquet) */
     
                        /* Rappel : Attention a l'ordre des octets (pour les mots de plus de 1 octet).         */
                        /*          Utilisez htons et htonl pour mettre les shorts et les longs au bon format. */
                        /*          Cela ne concerne pas les chars car la taille d'un char est de 1 octet.     */
     
                        ip.version    = 4;
                        ip.hlen       = 5; /* sizeof(ip) / 4 */
                        ip.tos        = 0;
                        ip.tot_len    = htons(ip_len);
                        ip.id         = htons(1);
                        ip.flags      = 0;
                        ip.offset     = 0;
                        ip.ttl        = 100;
                        ip.protocole  = IPPROTO_UDP;
                        ip.somme      = 0;
                        ip.ip_source  = inet_addr(IP_SOURCE);
                        ip.ip_dest    = inet_addr(IP_DEST);
     
                        ip.somme      = checksum(&ip, sizeof(ip));
     
                        udp.port_source  = htons(PORT_SOURCE);
                        udp.port_dest    = htons(PORT_DEST);
                        udp.tot_len      = htons(udp_len);
                        udp.somme        = 0;
     
                        memcpy(buf, &ip, sizeof(ip));
                        memcpy(buf + sizeof(ip), &udp, sizeof(udp));
                        memcpy(buf + sizeof(ip) + sizeof(udp), message, message_len);
     
                        ZeroMemory(&dest, sizeof(dest));
                        dest.sin_family       = AF_INET;
                        dest.sin_addr.s_addr  = inet_addr(IP_DEST);
                        dest.sin_port         = htons(PORT_DEST);
     
                        if (sendto(s, buf, ip_len, 0, (SOCKADDR *)&dest, sizeof(dest)) == SOCKET_ERROR)
                            fprintf(stderr, "La fonction sendto a echoue.\n");
                        else
                            printf("Message envoye !\n");
     
                        free(buf);
                    }
                }
     
                closesocket(s);
            }
     
            WSACleanup();
        }
     
        return 0;
    }
     
    USHORT checksum(void * lpData, size_t size)
    {
        USHORT * t = lpData;
        DWORD somme = 0;
        size_t i, n = size / sizeof(USHORT);
     
        for(i = 0; i < n; i++)
            somme += t[i];
     
        if (size % 2)
        {
            UCHAR * u = lpData;
            somme += u[size - 1];
        }
     
        while (HIWORD(somme))
            somme = HIWORD(somme) + LOWORD(somme);
     
        return LOWORD(~somme);
    }
    J'ai ensuite lancé la commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc zztest.c -lws2_32 -o zztest.exe
    Mon PATH contient le chemin suivant pour gcc : C:\Program Files\CodeBlocks\MinGW\bin
    Et le résultat n'est pas très probant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    C:/Program Files/CodeBlocks/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../libmingw
    32.a(main.o):main.c:(.text+0x104): undefined reference to `_WinMain@16'
    collect2: ld returned 1 exit status
    Je dois effectivement avoir un environnement pourri. Mais je ne sais pas trop où creuser.

  4. #4
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Là il s'agit maintenant d'un problème d'édition des liens et non plus d'un problème de compilation. Ton éditeur des liens (ld.exe) cherche la fonction WinMain (qui est une fonction requise dans une application graphique Windows) mais elle ne la trouve pas. Notre application est en effet une application console et non une application graphique, donc le point d'entrée doit être main et non WinMain. Il faut donc trouver le moyen de dire à ld.exe que ce qu'on compile est une application console (pour qu'elle cherche la fonction main à la place de WinMain) et non une application graphique. Normalement, il devrait automatiquement le savoir vu que notre fichier comporte une fonction main, mais bof. Et comment on le lui dit, je ne le sais pas hélas.

  5. #5
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Donc ça avance pas trop mal en fait.
    Je vais chercher dans ce sens.
    Merci pour la piste en tous cas.

  6. #6
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Ça tient de l'étrange.

    J'ai remplacé ma fonction "main" par "WinMain" pour voir le comportement du compilateur.
    Évidemment, j'ai eu un message d'erreur à la compilation car la fonction "WinMain" attend des arguments obligatoires

    J'ai ensuite remis "main" à la place de "WinMain", et la compilation est passé sans erreur.
    Un exécutable a été pondu et il fonctionne.

    Maintenant, je vais me pencher sur mon environnement sous Code::Block, car ça pèche toujours avec cet IDE.

    A+.
    Je vous tiendrai informé des résultats ...

Discussions similaires

  1. La programmation des sockets bruts sous Windows
    Par Melem dans le forum Articles
    Réponses: 4
    Dernier message: 18/04/2016, 16h15
  2. socket.MSG_DONTWAIT sous Windows
    Par matth_mm dans le forum Réseau/Web
    Réponses: 3
    Dernier message: 24/09/2010, 16h46
  3. Probleme socket RAW sous linux
    Par wbaccari dans le forum Réseau
    Réponses: 0
    Dernier message: 07/08/2009, 17h16
  4. Programmation de socket linux sous windows
    Par neuro6 dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 16/10/2007, 18h35
  5. Socket PHP sous windows
    Par souko dans le forum Langage
    Réponses: 4
    Dernier message: 25/07/2007, 10h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo