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é: 20 963 / 4 186

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

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (21)
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.
 

Fichier Zip

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

Historique

04 avril 2005 19:28:41 :
19 février 2007 16:40:34 :
Retrait d'adresse mail.

Commentaires et avis

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

signaler à un administrateur
Commentaire de Mithfindel le 11/07/2008 14:12:11

Bon tuto.
Dans UDP_Packet_Sender.cpp, le 4ème paramètre de la fonction sendto(...) permet de spécifier des flags de contrôle de la socket (c.f http://msdn.microsoft.com/en-us/library/ms740148(VS.85).aspx ).

HTH ;)

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Aide Sockets Winsock [ par VoLc0m ] voila mon pb :en C bien sur :) je dois, par socket, envoyer ca a une address (server counter strike) :The packet should start with 4 consecutive bytes Proxy TCP (rediriger une connexion TCP) [ par MetalDwarf ] Je suis en train de programmer un petit prog avec une couche reseau assez importante et j aimerais y integrer un proxy capable de rediriger toute conn Sockets - Broadcast UDP [ par Toadstool ] Je veux broadcaster un paquet UDP pour "pinger" les serveurs half-life présent sur un réseau local (cf. la source bot irc + scan de parties counter-st Programme ecoutant le traffic UDP-TCP [ par KoKa ] Bonjour,Je travaille sous linux et je voudrai ecrire un petit programme qui me permette de filtrer le traffic UDP et TCP avec un certain port de desti Raw Socket -> TCP/IP [ par krum ] Voila plus d'une semaine que je fouille/cherche sur les moteurs de recherches,les forums ..des sources,des tutos,des papers sur les raw sockets (sous Sockets asychrones et client serveur TCP [ par argali ] Bonjour,Est-ce qqun pourrait m'indiquer ou je pourrai trouver un cours complet sur les sockets asynchrones et leurs options (WSAAsyncSelect, FD_ACCEPT Tutoriel winsock [ par moumouteb ] Bonjour, Quelqu'un connaitrait un bon tutorial (en français de préférence) pour la programmation résaux avec winsock et sans MFC? Merci.-------------- Socket TCP/UDP [ par hobbes ] Bonjour,j ai cru comprendre qu il existe 2 types de sockets (TCP et UDP) pouvant permettre l echange de donnees entre 2 applications sur le reseau.Pou Tutoriel sockets [ par lgrenon ] SalutJe cherche un bon tutoriel sur les sockets en c/c++ (je travaille sous borland c++ builder 6)Si vous en connaissait un vous pouvez me filer l'adr SOS winsock! S.O.S! [ par GUERRIER_ABSOLU ] Salut amis du salut en C++. Je suis étudiant; j'essaie de réaliser un truc client-serveur(qui sera noté) avec les sockets sous Windows. J'ai lu le hel


Nos sponsors

Sondage...

CalendriCode

Septembre 2008
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
2930     

Consulter la suite du CalendriCode

Téléchargements

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



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,36 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.