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

Bibliothèques C++ Discussion :

Envoi de données sendto() problème select


Sujet :

Bibliothèques C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 23
    Points : 12
    Points
    12
    Par défaut Envoi de données sendto() problème select
    Bonjour,
    Je vous explique mon problème,
    Afin de faire des test de transmission entre 2 Pc je souhaite envoyer par l'intermediaire d'une trame IP (et ICMP) et du sendto.
    Grace au memset j'ajoute de '1' dans ma trame icmp et je souhaite l'envoyer en attendant un echo afin avec le temps et la quantité de donnée transmisent calculé la vitesse.
    Lorsque je remplit ma trame icmp de 0 (avec rien) cela marche mais lorsque je fait un memset avec des '1' cela bloque sur le select.

    Pourriez vous me dire ou est l'erreur

    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
    void Ping(CString Adresse, TabString* TabResult, int nbPing, int &NbLigne)
    {
        char *IP;
        SOCKET  sock;
        WSADATA wsaData;
        struct  sockaddr_in sin, from;
        int     envoi, recept;
        char    icmp_data[20000]; // 20 Ko de données
        char    recvbuf[MAX_PACKET];
        int     fromlen = sizeof(from);
        struct  hostent *phe, *sn;
        struct  in_addr in;
        char*   hostname;
        fd_set fdsr;
        struct timeval tv_timeout;
     
    	int lg = Adresse.GetLength();
    	char *Pinging = new char[lg];
    	//IP de CString à char*
    	for (int i=0; i<lg; i++)
    	{
    		Pinging[i] = Adresse.GetAt(i);
    	}
    	Pinging[lg] = '\0';
     
        // Initialisation et création du socket
    	WSAStartup(MAKEWORD(2,0),&wsaData);
        sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
     
    	 if(sock==INVALID_SOCKET)
        {
    		TabResult[NbLigne].StringPing.Format(_T("Erreur de creation du socket"));
    		NbLigne++;
            return;
        }
     
    	memset(&sin,0,sizeof(&sin));
        phe = NULL;
     
    	hostname = Pinging;
        phe = gethostbyname(hostname);
     
    	if(!phe)
        {
            TabResult[NbLigne].StringPing.Format(_T("Hôte inconnu, impossible de résoudre l'adresse %s.",hostname));
    		NbLigne++;
            return;
        }
     
    	memcpy(&(sin.sin_addr),phe->h_addr,phe->h_length);
        IP = inet_ntoa(sin.sin_addr);
     
    	if((strcmp(IP, Pinging) != 0) || (Resolv == 1))
        {
            in.s_addr = inet_addr(Pinging);
            sn=gethostbyaddr((char *)&in, 4, AF_INET);
            memset(&hostname,0,sizeof(hostname));
            if(Resolv == 1) hostname = sn->h_name;
            else hostname=phe->h_name;
            strcat(hostname, " [");
            strcat(hostname, IP);
            strcat(hostname, "]");
        }
     
    	if(phe) sin.sin_family = phe->h_addrtype;
        else sin.sin_family = AF_INET;
     
        int taille2;
        taille2 = sizeof(IpHeader) + sizeof(IcmpHeader);
     
    	TCHAR szMess[128];
    	wsprintf(szMess, _T("Envoi d'une requête sur %s avec %i octets de données :"), hostname, taille2);
    	MessageBox(NULL, szMess, _T("Erreur"),  MB_OK);
     
        // Initialisation du délai d'attente
        if(tpslimite == 0) tpslimite = DELAI;
     
    	while(envoye != nbPing)
    	{
            memset(icmp_data,'1',500); //remplissage avec 500 fois le caractère '1'
    		int lg(sizeof(icmp_data));
            id = (unsigned short)GetCurrentProcessId() + envoye;
            // Construction du paquet ICMP
    		int size=2000; //quantité de données que je souahite envoyer
    		IcmpHeader *icmp_hdr;
    		icmp_hdr = (IcmpHeader*)icmp_data; //creation de l'header de la trame icmp a partir de icmp_data
     
    		icmp_hdr->i_type     = 8; // Type du paquet ICMP : echo request
    		icmp_hdr->i_code     = 0; // Il n'y a pas de code spécifique pour ce type de paquet
    		icmp_hdr->i_id       = id;
    		icmp_hdr->i_seq = 1;
     
    		icmp_hdr->timestamp = GetTickCount(); // Initialisation du temps lors de l'envoi
    		// Somme de contrôle sur 16 bits
    		((IcmpHeader*)icmp_data)->i_cksum = CNetwork::checksum((unsigned short*)icmp_data, size); 
     
            // On envoie le paquet ICMP que l'on a construit
     
    		CString retour;
            envoi = sendto(sock, icmp_data, size, 0, (struct sockaddr *)&sin, size); // envoi = 2000 OK
    		envoi = WSAGetLastError(); // valeur = 0
     
            FD_ZERO(&fdsr);
            FD_SET(sock, &fdsr);
     
            tv_timeout.tv_sec = tpslimite/1000;
            tv_timeout.tv_usec = 0;
     
            findelai = 0;
    		do
            {
     
                if (select(sock+1, &fdsr, NULL, NULL, &tv_timeout) <= 0) // bloque jusqu'au timeout (10 secondes)
                {
                    // Dans le cas où le temps est écoulé, on veut sortir de la boucle
                    // on compte le paquet comme envoyé mais perdu
                    TabResult[NbLigne].StringPing.Format(_T("Délai d'attente de la demande depassé"));
                    perte++;
                    envoye++;
    				NbLigne++;
                    findelai = 1;
                }
                ...

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Utilisez un sniffer réseau pour voir le trafic.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 23
    Points : 12
    Points
    12
    Par défaut
    Est ce qu'un sniffer réseau peut-être intégrée a une classe en C++?

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Houla.
    Un sniffer réseau, c'est un programme pour voir le trafic réseau. Rien à voir avec C++.
    Je fais mention de cet outil pour savoir si le problème se posse à l'envoie du message ou à la réception des réponses.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 23
    Points : 12
    Points
    12
    Par défaut
    Après analyse avec ethereal, j'ai un probleme de checksum dans ma trame ICMP.

    Pourriez vous me dire où se trouve l'erreur dans le code au niveau du calcul.
    Voici la fonction que j'utilise

    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
    USHORT checksum(USHORT *buffer, int size) 
    { 
    	unsigned long cksum=0; 
     
    	while(size >1) 
    	{ 
    		cksum+=*buffer++; 
    		size -=sizeof(USHORT); 
    	} 
     
    	if(size ) 
    	{ 
    	cksum += *(UCHAR*)buffer; 
    	} 
     
    	cksum = (cksum >> 16) + (cksum & 0xffff); 
    	cksum += (cksum >>16); 
    	return (USHORT)(~cksum); 
    }

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    As-tu initialisé à zéro le champs checksum avant son calcul ? Pas la variable, mais l'emplacement dans buffer où tu vas écrire ce checksum.

    [EDIT] probablement pas car je lis memset(icmp_data,'1',500);. Et il me semble que le checksum n'est calculé que sur l'en-tête (à vérifier ?) et toi tu le calcules sur toute la trame ?
    Un petit conseil : découpe ta fonction pour faciliter la lecture.
    Un gros conseil : tu devrais revoir un peu la conception et utiliser les outils du C++ (std::string, std::vector, classes, ...).

Discussions similaires

  1. Réponses: 3
    Dernier message: 21/11/2006, 17h59
  2. Réponses: 5
    Dernier message: 14/08/2006, 04h04
  3. [AJAX]problème d'envoie de données méthode POST
    Par xave dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 07/07/2006, 16h35
  4. [AJAX] AJAX et envoie de données d'un formulaire
    Par gunderam dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 14/06/2006, 18h17
  5. [MySQL] Problème récupération de données avec un SELECT DISTINCT
    Par 12_darte_12 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 25/07/2005, 14h48

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