begin process at 2008 05 17 10:21:04
1 173 959 membres
86 nouveaux aujourd'hui
13 973 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

TUTORIAL : LES SOCKETS SOUS WIN (TCP & UDP)


Information sur la source

Catégorie :Tutoriaux Classé sous : tutoriel, sockets, winsock, tcp, udp Niveau : Initié Date de création : 31/12/2002 Date de mise à jour : 19/02/2007 16:40:33 Vu / téléchargé: 18 234 / 4 041

Note :
9,83 / 10 - par 6 personnes
9,83 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (20)
Ajouter un commentaire et/ou une note

Description

Ce tut est composé de :
_Un client TCP
_Un server TCP
_Un envoyeur de packets udp
_Un receveur de packets udp
+ Un code qui fait tout a la fois (+pratik)

Le tout commenté bien sur :)

J'y ai ajouté qq document que j'ai utilisé pour comprendre le fonctionement des sockets.
      

Conclusion

J'espere que sa aidera ceux qui débutent en la matiere.
Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

04 avril 2005 19:28:41 :
19 février 2007 16:40:34 :
Retrait d'adresse mail.
  • signaler à un administrateur
    Commentaire de Xs le 31/12/2002 16:45:42

    bien. mais tu pourrais "developper" : par exemple, tu pourrrais recuperer l'ip destination, source, port, etc... et les afficher dans le receveur. ca serais cool, parce que je cherche comment faire, lol :)

  • signaler à un administrateur
    Commentaire de vbnul le 01/01/2003 10:19:41

    Pour le client, c simple de récuperer l'ip destination et le port
    Mais pour le server...
    Faudrait regarder si c pas stocké dans SOCKADDR_IN
    Ou bien faire du RAW(chaque packet contient tt ces infos)
    Pour l'UDP c pareil pour le receveur...

  • signaler à un administrateur
    Commentaire de Xs le 01/01/2003 16:17:07

    oui, effectivement : recuperer le destinataire+port, mais ce qui m'interresse c'est la source : ip et port. et ca, je ne sais pas. D'apres toi, c'est possible de dire tout cela depuis l'emmetteur mais de recuperer les infos des packets pour afficher les infos chez le receveur, c'est plus dur ?? je vais chercher de mon coter. merci.

  • signaler à un administrateur
    Commentaire de BlackWizzard le 02/01/2003 15:32:06 administrateur CS

    C cool!
    C le genre de tut que je cherche...
    Tu vx pas ecrire des tuts pour mon site?
    http://underground.blackwizzard.com
    repond par msg sur le site ou par mail postmaster@blackwizzard.com

  • signaler à un administrateur
    Commentaire de BlackGoddess le 06/01/2003 13:48:16

    oui, l'adresse et le port sont contenus dans SOCKADDR_IN
    le port dans sin_port et l'adresse dans sin_addr

    pour le port, il faut faire ntohs(sa_in.sin_port) pour l'avoir,
    et pour l'ip il faut faire inet_ntoa(sa_in.sin_addr)

  • signaler à un administrateur
    Commentaire de vbnul le 09/01/2003 19:17:25

    sa donne l'addr ip distante en server ??

  • signaler à un administrateur
    Commentaire de sena le 14/02/2003 12:00:35

    Très bien le code !
    J'utilise 2 postes pour ton client-serveur en UDP.
    Ca fonctionne très bien. bravo!
    Mais comme je suis un peu barré il faut que ces 2 prog tournent sur la même machine en même temps.
    En clair: le client envoi sur le port n°11060 à l'adresse 127.0.0.1 (ou bien l'ip de la machine) et le serveur écoute sur le port n°11060.
    Et bien ca ne fonctionne pas ! (pourtant seule l'adresse ip change lorsque l'on utilise 2 postes)

    Quelqu'un sait pourquoi on ne peut pas faire tourner ceci sur 1 machine?

  • signaler à un administrateur
    Commentaire de sena le 18/04/2003 14:11:16

    je me répète, TUTORIAL EXCELLENT.

    Par contre j'ai vu d'autre code qui ressemble au tien mais a la fin, ils ont cette ligne en plus:
    closesocket(sock);

    Pourkoi toi tu ne fermes pas tes sockets?
    C'est WSACleanup() qui le fait?

  • signaler à un administrateur
    Commentaire de BlackGoddess le 18/04/2003 18:13:48

    ca me parait plus propre de libérer les ressources au fur et a mesure, surtout dans un tutorial : en effet si qq1 reprend ce code avec plusieurs sockets utilisés les uns apres les autres, il ne va faire qu'un WSAStartup/WSACleanup, mais ne va pas libérer les ressources demndées par les sockets au fur et à mesure -> c'est du gaspillage

  • signaler à un administrateur
    Commentaire de vbnul le 28/05/2003 13:32:30

    Effectivement, il vaut mieux fermer les sokets avec closesocket et vider les WSA avec WSACleanup, autant faire les 2...
    Chez moi tout marche trés bien en local, d'ailleurs je n'ai amais testé en wan :$
    Si vous voulez d'autres trucs sur le sockets, mon site commence à etre fourni (http://www.progzone.ht.st)

  • signaler à un administrateur
    Commentaire de CptLuthor le 08/11/2004 10:07:32

    quand on connecter en VPN , c quel protocol : TCP ou UDP ?

    il ya aussi le protocol PPTP, est-il du meme genre que TCP ou UDP  ou est ce un protocol secondaire  ? cest a dire que c'est un protocol encapsuler par TCP ou UDP

    Quand je suis connecter avec un pot par VPN, on peut se voir dans les jeux, par exemple quake3,  le fait que lon puisse se voir  c'est grace a quel protocol ?

    merci

  • signaler à un administrateur
    Commentaire de mythic_kruger le 20/03/2005 09:39:48

    Un bon code de tutorial. Hyper-commenté. La classe.

  • signaler à un administrateur
    Commentaire de NitRic le 05/04/2005 04:51:36

    Si tu permets, j'aimerais bien ajouter quelques petites choses, alors voilà:

    pour initialiser Winsock:

    int LoadWinsock( unsigned short wVersion )
    {

    int ret;
    WSADATA wsd;

    if ( 0 == wVersion )
    wVersion = MAKEWORD(2, 0);

    if ( 0 == (ret = WSAStartup( wVersion, &wsd )) )
    {
                    /* version 2.x(2.0, 2.2, ...) */
    if ( LOBYTE(wVersion) == LOBYTE(wsd.wVersion) )
    return 0;

    WSACleanup();
    return WSAVERNOTSUPPORTED;
    }

    return ret;

    }


    printf("%s","\nPort : ");
    tu pourrais faire simplement ceci: printf("\nPort: ");

    Sous Windows, un SOCKET est un entier oui, mais non signé(unsigned int) contrairement sous Linux ou c'est un entier signé(int) ...

    Pour tes scanf("%s", buffer); tu devrais plutôt faire:

    scanf( "%50s", buffer ); /* pour éviter d'aller écrire trop loin dans `buffer` */
    et ensuite, utiliser strlen() lors des envois:

      scanf("%50s", buffer);
      buffer[sizeof(buffer)] = '\0'; /* s'assure d'avoir un '\0' */

      length = strlen( buffer );
      error = send( uSocket, buffer, length, 0 );

    et de plus, tu évite les memset() ...

    Tu pourrais aussi utiliser gets() ou encore fgets() mais bon ...

    connect() ne renvoie pas `true` mais -1(SOCKET_ERROR) en cas d'erreur ...

    Si connect() renvoie -1(SOCKET_ERROR) tu devrais vérifier que ton socket n'est pas bloquant/en progression:

    int ret = connect( ... );
    if ( (ret == SOCKET_ERROR) && (WSAEWOULDBLOCK != WSAGetLastError()) )
    {
        puts("ERROR!!!");
    }
    else puts("GOOD");

    les fonctions htonl(), htons() et compagnie ne convertissent pas les données qu'elles recoivent en nombre _pour Windows_ mais pour ... hummm ... je sais pas comment `bien` le traduire en francais mais voilà en anglais:
    "The htons function takes a 16-bit number in host byte order and returns a 16-bit number in network byte order(big-endian) used in TCP/IP networks."

    Même chose pour htonl(), sauf que htonl() c'est 32bits et non 16bits ...

    big-endian : 4321
    little-endian : 1234
    middle-endian : 2143/3412

    recv() renvoie, soit -1(une erreur), soit 0(connexion fermé `correctement`) ou une valeur positif(des données ont été lus) ...

    void main() /* c'est pas bien ca ... */
    {
    }

    int main() /* ca c'est bien */
    {
      return 0;
    }

    Au fait, un `port` est un entier 16bits non signé(unsigned short) et non un entier 16/32/64/..bits signé ... il ne faut pas oublier qu'un `int` est dépendant du système, 16, 32, 64, ...

    Pour le serveur(tcp) tu as mis `err = scanf(...);`, tu devrais plutôt vérifier send() & recv() ...

    char ip[15]; << c'est trop petit
    000.000.000.000 == 3*4=12+3=15, l'espace pour le '\0' il est ou???

    #define IPV4_LENGTH (17) /* taille raisonable */
    char ip[IPV4_LENGTH]; /* la c'est bien & safe ... */

    Pour INADDR_ANY faut quand même utiliser htonl() ...

    Voilà, je crois que c'est tout ce que j'avais à ajouter ...

    @++;



    ~(.:: NitRic ::.)~

  • signaler à un administrateur
    Commentaire de viran le 14/02/2006 21:38:50

    Bonjour a tous, j'aurais besoin de votre aide, j'ai cherché des tutoriaux de socket sur le net et a chaque fois il me sort la meme erreur, il commence a compiler, ne me sort pas d'erreur dans mon script et a chaque fois, sur compilateurs differents avec ce code simplifier a l'extreme :

    "#include<stdio.h> //Fichier d'inclusion pour printf, scanf, system...
    #include<winsock2.h>//Pour tout se qui touche aux sockets

    #pragma comment(lib,"ws2_32.lib")//tjs pour les sockets

    void main()
    {
    WSADATA wsa;
    WSAStartup(MAKEWORD(2,0),&wsa);//MAKEWORD dit qu'on utilise la version 2 de winsock

    }"

    voici l'erreur :

    "collect2: ld returned 1 exit status
    Process terminated with status 1 (0 minutes, 0 seconds)
    0 errors, 0 warnings"

    Merci de m'aider.

  • signaler à un administrateur
    Commentaire de viran le 14/02/2006 21:39:53

    Excusez moi j'allais oublier : je suis sous windows XP

  • signaler à un administrateur
    Commentaire de undertherises le 27/03/2007 15:14:00

    genre c'est du c++ alors que c'est du c. Wé super

  • signaler à un administrateur
    Commentaire de Renfield le 27/03/2007 15:18:46 administrateur CS

    en voilà une remarque "genre" constructive

  • signaler à un administrateur
    Commentaire de realic le 03/05/2007 15:54:33

    Bonjour,

    J'ai trouvé un code qui est très intéressant, mais qui ne me permet pas de recevoir des fichiers.
    Je peux recevoir ce que dit le serveur (ce qui est intéressant, mais pas pour le moment).
    A partir du moment où je suis sur le point de recevoir un fichier, il me met :
    450 Write Error: bad file descriptor.
    C'est de l'envoi FTP, pas HTTP (j'ai le même en HTTP, ca marche très bien).
    Est-ce que quelqu'un sait ce qu'il me manque pour que ca fonctionne ??
    Merci.

    voici le code :
    #include "stdafx.h"
    #include <stdio.h>
    #include <winsock.h>
    #include "wininet.h"

    #ifndef SD_SEND
    #define SD_SEND 1
    #endif

    #define BUFFER_SIZE 5*1024
    static HWND hDlg;
    static BYTE buff[BUFFER_SIZE], *Buffer;
    #define Mes(szTXT) MessageBoxA(hDlg, szTXT,"nvond",MB_OK);
    static bool init_winsock(void)
    {
       WSAData Data;
       int Code;
       std::ostringstream oss;
       if((Code=WSAStartup(MAKEWORD(1, 1),&Data)) != 0)
       {
       oss<<"erreur dans WSAStartup() : "<<Code;
    //      printf("erreur dans WSAStartup() : %d\n", Code);
          return false;
       }
       return true;
    }

    static SOCKET etablir_connexion(u_long adresse_distante, u_short port) {
       sockaddr_in sinDistant;
       SOCKET sd = socket(AF_INET, SOCK_STREAM, 0);

       if(sd!=INVALID_SOCKET) {
           sinDistant.sin_family = AF_INET;
           sinDistant.sin_addr.s_addr = adresse_distante;
           sinDistant.sin_port = port;
           if(connect(sd,(sockaddr*)&sinDistant, sizeof(sockaddr_in))==SOCKET_ERROR)
                 sd = INVALID_SOCKET;
      }
      return sd;
    }

    static u_long resoudre_adresse(char* hote) {
       hostent* pHE;
       u_long adresse_distante = inet_addr(hote);

       if(adresse_distante == INADDR_NONE) {
          pHE = gethostbyname(hote);
          if(pHE == 0) return INADDR_NONE;
          adresse_distante = *((u_long*)pHE->h_addr_list[0]);
       }
       return adresse_distante;
    }

    static int connectionFtp(HWND hwnd, std::string adr)
    {
    char *Hote = "anonymous.ftp.ovh.net";//"ftp.free.fr";//"cns.free.fr";
    int Port = 21;

    init_winsock();

    u_long adresse;
    SOCKET sd;
    char *requete;
    char tampon;

    // Trouver l'adresse de l'hôte
    std::ostringstream oss;
    oss<<"Recherche de l'hôte... "<< Hote;
    MessageBoxA(hwnd,oss.str().c_str(),"xj",MB_OK);
    oss.clear();
    adresse = resoudre_adresse(Hote);
    if(adresse==INADDR_NONE)
    {
    MessageBoxA(hwnd,"Echec !","xj",MB_OK);
    //    printf("Echec !\n");
       return 3;
    }
    MessageBoxA(hwnd,"Connexion en cours !","xj",MB_OK);
    //printf("Connexion en cours !\n");
    sd = etablir_connexion(adresse, htons(Port));
    if(sd!=INVALID_SOCKET) printf("Connecté !\n");

    // envoi de la requête
    requete="ftp anonymous.ftp.ovh.net\r\nUSER anonymous\r\nPASS a.a@msn.fr\r\nCWD ankamagam\r\nREST 0\r\nRETR Errata.txt\r\nquit\r\n\r\n";//\r\n/*RETR Errata.txt\r\n*/
    send(sd, requete, (int)strlen(requete), 0);
    std::ostringstream oss1;
    // réception de la réponse
    DWORD Recu=0;
    DWORD Ecrit=0;
    int rep;
    while(rep=recv(sd,&tampon,1,0)!=0 )
    {
    regarder(rep);
    regarderConnect(rep);
    oss1<<tampon;
    // Recu++;
    //  printf("%c", tampon);
    }
    //oss1<<tampon;
    MessageBoxA(hwnd,oss1.str().c_str(),"xj",MB_OK);
    /*
    if(oss1.str().c_str()[Recu-3]=='1' && oss1.str().c_str()[Recu-2]=='2' && oss1.str().c_str()[Recu-1]=='5')
    {
    oss1.clear();
    std::ostringstream oss2;
    Recu=0;
    while(recv(sd,tampon,1,0)!=0 && !(oss2.str().c_str()[Recu-2]==')' && oss2.str().c_str()[Recu-1]=='.'))
    {
    oss2<<tampon;
    Recu++;
    }
    MessageBoxA(hwnd,oss2.str().c_str(),"xj",MB_OK);
    }*/
    //hOpenFile = ::FtpOpenFileA(hConnect,strFileNameAtServer.c_str(), GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 1);

    FILE* File;
    //BYTE* Buffer;
    char* buffer=new char[4*1024];
    File = (FILE*)CreateFileA("Errata.txt", FILE_ALL_ACCESS, FILE_SHARE_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    HANDLE hOpenFile = NULL;
    DWORD ToRead=4*1024;
    DWORD Size=24017;

    // HINTERNET hOpenFile;
    HINTERNET  hConnect = NULL;
    hOpenFile = ::FtpOpenFileA(hConnect,"Errata.txt", GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 1);
    if (!InternetReadFile (hOpenFile, (LPVOID)Buffer, ToRead,  &Size) )
    {
    fclose (File);
    //CString strMsg;
    //string strReposeFromServer;
    //GetLastResponse(strReposeFromServer);
    //strMsg.Format(L"Error:%d\nDescription:%s", GetLastError(), strReposeFromServer.c_str());
    //AfxMessageBox(strMsg, MB_OK);
    return 0;
    }
    WriteFile(File, Buffer, Recu, &Ecrit, 0);
    //MessageBoxA(hwnd,oss1.str().c_str(),"xj",MB_OK);

    MessageBoxA(hwnd,"FINI","oxi",MB_OK);
    // quitter correctement winsock
    send(sd,"quit\r\n\r\n", (int)strlen(requete), 0);
    shutdown(sd, SD_SEND);
    closesocket(sd);
    WSACleanup();
    return 0;
    }

  • signaler à un administrateur
    Commentaire de maladedede le 21/06/2007 15:48:14

    Bonjours (bonne source merci).
    J'ai une question.

    En TCP on sait que si l'on doit recevoir par exemple 1024 Octects. On va faire recv() et si avec le premier recv() on recoit pas les 1024 octects on va refaire recv() autant de fois qu'il le faudra pour pouvoir mettre bout à bout les 1024 octects.

    Mais en UDP comment cela fonctionnne si on recoit pas les 1024 octects prevu avec recvfrom(), on perd le reste des données ?
    Où doit-on refaire recvfrom() tant qu'il le faudra comme en TCP ?

    Merci

  • signaler à un administrateur
    Commentaire de maladedede le 22/06/2007 01:19:29

    j'ai posé ma question sur le forum: http://www.cppfrance.com/infomsg_UDP_968594.aspx

Ajouter un commentaire

Discussions en rapport avec ce code source

Appels d'offres

Pub



Snippets en rapport

CalendriCode

Mai 2008
LMMJVSD
   1234
567891011
12131415161718
19202122232425
262728293031 

VS Express FR Gratuit !

VS Express en français et 100% gratuit !

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS