[C++] Pingen funktioniert nicht wie es soll



  • Hi Folks,

    Ich schreibe gerade an einem Pingprogramm, das zehn verschiedene Hosts anpingt. So weit funktioniert es auch.
    Da auch drei Webserver angepingt werden (und bei google z.B. die IP öfters ändert) habe ich eine Funktion geschrieben, die den Hostnamen auflöst, wenn es einer ist. (Der Code ist teilweise vom Tut von C-worker.ch)
    Nun immer wenn ich tw.yahoo.com anpinge, bekomme ich einmal ein Timeout und dann bleibt das Programm einfach stehen.
    Dann fiel mir auf, dass die IP 202.43.195.52 (oder auch tw.yahoo.com) in 885205962 aufgelöst wird. (Network Byte Order).
    Bei allen anderen Addresssen sind es zehn Ziffern.
    Kann es irgendwie sein, dass mein Programm da Scheiße baut, oder wieso kann ich den Server nicht pingen?

    Ich bin langsam echt verzweifelt, das geht nun schon Tagelang so... 😞

    Danke euch schonmal,
    HdZ



  • He, hat denn niemand eine Ahnung?
    Fehlen euch Angaben?
    Bin ich im falschen Forum?
    Bitte antwortet doch!



  • Du bist im falschen Forum, hab vergessen es zu verschieben, sorry.

    Aber Tip: Auch im WinAPI-Forum wird dir niemand sagen können, ob deine Funktion stimmt wenn du keinen Quellcode postest 😉

    MfG SideWinder



  • Dieser Thread wurde von Moderator/in SideWinder aus dem Forum DOS und Win32-Konsole in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • HdZ schrieb:

    Dann fiel mir auf, dass die IP 202.43.195.52 (oder auch tw.yahoo.com) in 885205962 aufgelöst wird. (Network Byte Order).
    Bei allen anderen Addresssen sind es zehn Ziffern.
    Kann es irgendwie sein, dass mein Programm da Scheiße baut, oder wieso kann ich den Server nicht pingen?

    Die IP-Umrechnung stimmt (das sind ja nur zwei verschiedene Ausgabeformate für dieselbe Sache).

    Wie SideWinder schon geschrieben hat, ohne etwas Code kann keiner außer dir den Fehler finden.



  • Also, hier mal ein paar Code Schnipsel:

    long get_ip_by_name(char *ip_or_host, SOCKADDR_IN* addr1){ 
       unsigned long ip;
       HOSTENT* he;
    
       ip = inet_addr(ip_or_host);   
       if(ip!=INADDR_NONE){
          addr1->sin_addr.s_addr=ip;
          return 0;
       }
       else{
          he = gethostbyname(ip_or_host);
       }
       if(he == NULL){
          cout << "Fehler: Konnte Hostname nicht auflösen: " << ip_or_host << endl;
          system("pause");
          return SOCKET_ERROR;
       }
       else{
          memcpy(&(addr1->sin_addr),he->h_addr_list[0], sizeof(in_addr));
          return 0;
       }
       return 0;
    }
    

    Die Funktion löst den Hostnamen auf, falls es einer ist.
    Aufgelöst wird ja korrekt...

    char host_or_ip[15] = "";
    
    switch (i){
       case 1: sprintf(host_or_ip, "%s", ip_in_1); break; 
       case 2: sprintf(host_or_ip, "%s", ip_in_2); break;
       case 3: sprintf(host_or_ip, "%s", ip_in_3); break;
       case 4: sprintf(host_or_ip, "%s", ip_in_4); break;
       case 5: sprintf(host_or_ip, "%s", ip_in_5); break;
       case 6: sprintf(host_or_ip, "%s", ip_in_6); break;
       case 7: sprintf(host_or_ip, "%s", ip_in_7); break;
       case 8: sprintf(host_or_ip, "%s", ip_in_8); break;
       case 9: sprintf(host_or_ip, "%s", ip_in_9); break;
       case 10: sprintf(host_or_ip, "%s", ip_in_10); break;
    }
    cout << endl << "Host: " << host_or_ip << endl;
    
    long net_ip = get_ip_by_name(host_or_ip, &addr);
    cout << "Network Byte Orderaddr: " << addr.sin_addr.s_addr << endl;
    //addr.sin_addr.s_addr = net_ip;
    addr.sin_family = AF_INET;
    addr.sin_port = 0; //unused
    
    icmp_header.ucType = 8; //ICMP Echo Request
    icmp_header.ucCode = 0;
    icmp_header.ulTimeStamp = GetTickCount(); // Millisekunden seit Systemstart
    icmp_header.usID = (unsigned short) GetCurrentProcessId();
    icmp_header.usSequence = 0;
    icmp_header.usCheckSum = 0; //before calc set to zero
    
    sprintf(sz_data, "%s", "dadadadadadadadadad");
    packet_len = write_header(icmp_header, sz_data, 20, sz_packet);
    ((icmp_header_t *) sz_packet)->usCheckSum = checksum((unsigned short *) sz_packet, packet_len);
    

    Hier wird das ICMP Paket geschrieben.

    Und dann versendet...

    if(sendto(socket, sz_packet, packet_len, 0, (SOCKADDR *) &addr, sizeof(addr)) == SOCKET_ERROR){
       wsa_failure = WSAGetLastError();
       cout << endl << "Fehler: sendto, fehler code: " << wsa_failure << endl;
       closesocket(socket);
       continue;
    }
    

    Gut, soweit scheint noch alles zu funktionieren, denn ich bekomme erst bei recv() den Fehler 10060 (Timeout), was abe nicht sein kann, da ich über die Konsole sehr wohl den Host pingen kann.

    Nach send() kommt noch folgendes in main.cpp

    start = timeGetTime();                                        //Get begin-timestamp
             if(recv_packet(socket, sz_packet, 65000 + sizeof(ip_header_t) + sizeof(icmp_header_t), &icmp_header) == true){
               end = timeGetTime();                                       //Get stop-timestamp 
               ms = ms+(end-start);
             }
    

    So, ich hoffe das passt so, falls noch etwas fehlt bitte fragen,
    ich würde auch einfach den ganzen Source anhängen, wenn ich wüsste wie. 😉

    Danke euch schonmal,
    HdZ



  • Also, da niemand auf meinen Beitrag antwortet, hier ein Beispiel.

    Wenn ich die IP von Google eingebe, kann ich pingen.
    Von tw.yahoo.com nicht. (Div. andere auch nicht)

    #include <iostream>
    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    unsigned long x_send;
    unsigned long x_recv;
    unsigned long x_fail;
    unsigned long x_time_out;
    unsigned long x_temp;
    
    using namespace std;
    
    typedef struct{
       unsigned char ucType;	// ICMP Message Typ
       unsigned char ucCode;	// Message Interner (Fehler-)Code
       unsigned short usCheckSum;  	// Checksum für das ICMP Paket
       unsigned short usID;	// ID des Pakets, oft wie Port bei TCP / UDP genutzt
       unsigned short usSequence;	// Sequenznummer, bei mehreren typgleichen, (sinn-)zusammenhängenden Paketen
       unsigned long ulTimeStamp;	// Zeitstempel beim Abesenden
    } icmp_header_t;
    
    typedef struct{
       unsigned int ip_head_len:4;	// Länge des IP-Headers
       char szAdditionalData[23];	// Enthält weitere Daten die nicht interessieren
    } ip_header_t;
    
    //Prototypen *******************************************************************
    unsigned short Checksum(unsigned short *p_usBuffer, int iSize);              //*
    int start_winsock(void);                                                     //*
    SOCKET create_RAW_socket(bool fAutoIPHeader);                                //*
    bool set_time_out(SOCKET con_sock, unsigned int nTimeOut);                   //*
    unsigned short write_header(icmp_header_t hdrICMPHeader, char *szData, unsigned short usDataLen, char *szPacket);
    bool ReceivePacket(SOCKET sckSocket, char *szPacket, size_t nMaxLength, icmp_header_t *pOutICMPHeader);
    // *****************************************************************************
    
    int main(){
       char ip_in[15] = "202.39.83.194";
       long rc;
       SOCKET con_sock;
       char sz_data[20], sz_packet[32]; // 32 = 20 + sizeof(icmp_header_t)
       unsigned short packet_len;
       icmp_header_t hdrICMPHeader;
       SOCKADDR_IN saDestination;
    
       //cin >> ip_in;
    
       //Winsock starten ***********************************************************
       rc = start_winsock();
       if(rc!=0){
          cout << "Fehler: startWinsock, fehler code: " << rc << endl;
          return 1;
       }
       else{
          //cout << "Winsock gestartet!\n";
       }
    for(;;){
       //Paket erstellen ***********************************************************
       saDestination.sin_addr.s_addr = inet_addr(ip_in);
       saDestination.sin_family = AF_INET;
       saDestination.sin_port = 0; //unbenutzt
    
       hdrICMPHeader.ucType = 8; // ICMP Echo Request
       hdrICMPHeader.ucCode = 0;
       hdrICMPHeader.ulTimeStamp = GetTickCount(); // MS seit Sys Start
       hdrICMPHeader.usID = (unsigned short) GetCurrentProcessId(); // if(hdrICMPHeader.usID == GetProccessId()) eigenes Paket
       hdrICMPHeader.usSequence = 0;
       hdrICMPHeader.usCheckSum = 0; // vor dem berrechnen auf Null setzen!
    
       sprintf(sz_data, "%s", "pingpingpingpingping");
       packet_len = write_header(hdrICMPHeader, sz_data, 20, sz_packet);
       ((icmp_header_t *) sz_packet)->usCheckSum = Checksum((unsigned short *) sz_packet, packet_len);
    
       //RAW Socket erstellen ******************************************************
       con_sock = create_RAW_socket(true);
    
       //Timeout für Socket setzen auf 3000 ms *************************************
       set_time_out(con_sock, 3000);
    
       //return(sendto(con_sock, sz_packet, packet_len, 0, (SOCKADDR *) &saDestination, sizeof(saDestination)) != SOCKET_ERROR ? 0 : 1);
       Sleep(100);
       if(sendto(con_sock, sz_packet, packet_len, 0, (SOCKADDR *) &saDestination, sizeof(saDestination)) == SOCKET_ERROR){
          x_fail += 1;
          system("cls");
          cout << x_send << "\tPings gesendet\n" << x_recv << "\tAntworten empfangen\n" << x_time_out << "\tTimeouts\n\n" << x_fail << "\tSendefehler\n\n" << "Letzter Fehler: " << x_temp << endl;
          continue;
       }
       else{
          x_send += 1;
          system("cls");
          cout << x_send << "\tPings gesendet\n" << x_recv << "\tAntworten empfangen\n" << x_time_out << "\tTimeouts\n\n" << x_fail << "\tSendefehler\n\n" << "Letzter Fehler: " << x_temp << endl;
       }
    
       if(ReceivePacket(con_sock, sz_packet, 65000 + sizeof(ip_header_t) + sizeof(icmp_header_t), &hdrICMPHeader) == true){
          x_recv += 1;
          system("cls");
          cout << x_send << "\tPings gesendet\n" << x_recv << "\tAntworten empfangen\n" << x_time_out << "\tTimeouts\n\n" << x_fail << "\tSendefehler\n\n" << "Letzter Fehler: " << x_temp << endl;
          //cout << "Ping empfangen!\n";
          //system("pause");
       }
    }
       system("pause");
       return 0;
    }
    
    int start_winsock(void){
       WSADATA wsa;
       return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    //Funktionen *******************************************************************
    unsigned short Checksum(unsigned short *p_usBuffer, int iSize){
       unsigned long lCheckSum = 0;
       while(iSize > 1){
          lCheckSum += *p_usBuffer++;
          iSize -= sizeof(unsigned short);
       }
       if(iSize){
          lCheckSum += *(unsigned char*)p_usBuffer; // + 0 entfällt, da überflüßig
       }
       lCheckSum = ((lCheckSum >> 16) + (lCheckSum & 0xffff)) + (lCheckSum >> 16);
       return (unsigned short)(~lCheckSum);
    }
    
    SOCKET create_RAW_socket(bool fAutoIPHeader){
       if(fAutoIPHeader){
          return socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
       }
       else{
          return socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
       }
    }
    
    bool set_time_out(SOCKET sock, unsigned int nTimeOut){
       unsigned int nMillis = nTimeOut;
       return setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &nMillis, sizeof(nMillis)) != SOCKET_ERROR;
    }
    
    unsigned short write_header(icmp_header_t hdrICMPHeader, char *szData, unsigned short usDataLen, char *szPacket){
       memcpy(szPacket, &hdrICMPHeader, sizeof(icmp_header_t));
       memcpy(szPacket + sizeof(icmp_header_t), szData, usDataLen);
       return usDataLen + sizeof(icmp_header_t);
    }
    
    bool ReceivePacket(SOCKET sckSocket, char *szPacket, size_t nMaxLength, icmp_header_t *pOutICMPHeader){
       char szBuffer[1024];
       ip_header_t *pIPHeader;
       icmp_header_t *pICMPHeader;
       SOCKADDR_IN saFrom;
    
       while(true){
          int nResponseLen = 0;
          int nFromLen = sizeof(saFrom);
    
          nResponseLen = recvfrom(sckSocket, szBuffer, 1024, 0, (SOCKADDR *) &saFrom, &nFromLen);
          if(nResponseLen == SOCKET_ERROR){
             //cout << "Fehler: " << WSAGetLastError() << endl;
             x_temp = WSAGetLastError();
             if(x_temp == 10060){
                x_time_out += 1;
             }
             return false;
          }
          pIPHeader = (ip_header_t *) szBuffer;
          pICMPHeader = (icmp_header_t *) (szBuffer + pIPHeader->ip_head_len * 4); // ip_head_len wird in doubleword's (int's) gespeichert, daher * 4
          if(pICMPHeader->usID != GetCurrentProcessId()){ // not our packet
             continue;
          }
          memcpy(szPacket, szBuffer + pIPHeader->ip_head_len * 4 + sizeof(icmp_header_t), min(nMaxLength, nResponseLen - pIPHeader->ip_head_len * 4 - sizeof(icmp_header_t)));
          memcpy(pOutICMPHeader, pICMPHeader, sizeof(icmp_header_t));
          return true;
       }
    }
    

    Bitte helft mir, ich komm einfach nicht weiter!

    Danke,
    HdZ



  • Mir fällt da nix am Code auf...
    Alternativmöglichkeit wäre die icmp.dll von Microsoft zu verwenden.
    http://www.sockets.com/ms_icmp.htm
    Die icmp.dll gibts auch unter WinXP noch 😉
    Ich hab mal irgendwann nen Beispielprogramm dazu gebaut:
    http://www.geeky.de/cpp/tnt/tipp08.c



  • Danke,

    werde mich mal damit beschäftigen,
    eventuell findet ja noch irgendjemand den Fehler.
    Probiert das Prog halt mal aus...

    Danke nochmal,
    HdZ



  • Ich bin Anfänger und darum würde ich gerne wissen welchen Compiler du verwendest. 😕



  • HdZ schrieb:

    Danke,

    werde mich mal damit beschäftigen,
    eventuell findet ja noch irgendjemand den Fehler.
    Probiert das Prog halt mal aus...

    Danke nochmal,
    HdZ

    Bei mir funktioniert der Quellcode wunderbar und ich erhalte nie einen Timeout (hab's jetzt bis 30 laufen lassen).

    mfg.


Anmelden zum Antworten