Asci Zeichen per UDP senden



  • Hallo zusammen,

    ich versuche gerade ein serielles Gerät, was an einem RS232->Ethernet Umsetzer hängt, mit eines selbst geschriebenen UDP (Vorgabe) Programms anzusprechen. Dem Gerät muss ein "r" übermittelt werden, bevor es seine Daten ausgibt. Folgende Einstellungen sind im Umsetzer eigestellt:

    UDP Port (local) = 2002
    Destination = Meine IP
    UDP Port (Dest) = 2002

    Wenn ich das Terminalprogramm Hercules benutze (UDP Modus), hier unter Module IP die Umsetzter IP und unter Port/Local Port die angegebenen Ports eintrage, funktioniert alles wunderbar. Bei Übertragung eines "r" bekomme ich die entsprechende Antwort in Form einer Zahl.
    Ich versuche das selbe mit folgendem Programm zu erreichen:

    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    
    int startWinsock(){
        WSADATA wsa;
        return WSAStartup(MAKEWORD(2,0), &wsa);
    }
    
    int main()
    {
        long a;
        SOCKET s;
        char buf[256]="";
        char buf2[256]="";
        SOCKADDR_IN addr;
        SOCKADDR_IN remoteAddr;
        int         remoteAddrLen=sizeof(SOCKADDR_IN);
    
        /// WinSock starten
        a=startWinsock();
        if(a != 0)
        {
            printf("Fehler: startWinsock, fehler code: %li\n", a);
            return 1;
        }
        else
        {
            printf("WinSock gestartet!\n");
        }
    
        /// UDP Socket erstellen
        s=socket(AF_INET, SOCK_DGRAM, 0);
        if(s==INVALID_SOCKET)
        {
            printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n", WSAGetLastError());
            return 1;
        }
        else
        {
            printf("UDP Sockel erstellt!\n");
        }
    
        /// Adresse vorbereiten
        addr.sin_family         = AF_INET;
        addr.sin_port           = htons(2002);
        addr.sin_addr.s_addr    = ADDR_ANY; // Alternativ hatte ich hier die IP des Umsetzers stehen (wie in Hercules), aber es ändert nichts
    
        /// Daten senden
        buf[0]='r';
    
        a=sendto(s, buf, strlen(buf),0,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
        if(a==SOCKET_ERROR)
        {
            printf("Fehler: sendto, fehler code: %d\n",WSAGetLastError());
            return 1;
        }
        else
        {
            printf("%d Bytes gesendet!\n", a);
        }
        /// Daten empfangen
        a=recvfrom(s,buf2,256,0,(SOCKADDR*)&remoteAddr,&remoteAddrLen);
        if(a==SOCKET_ERROR)
        {
            printf("Fehler: recvfrom, fehler code: %d\n",WSAGetLastError());
            return 1;
        }
        else
        {
            printf("%d Bytes empfangen!\n", a);
            buf[a]='\0';
            printf("Empfangene Daten: %s\n",buf);
        }
        return 0;
    }
    

    Mein "r" wird anscheinend noch übertragen, aber dann hängt alles beim Empfangsprozess. Hier werden keine Daten empfangen. Ich vermute natürlich, dass schon beim Sendevorgang ein Fehler auftritt, kann diesen aber nicht finden.

    Weiß vll. jmd. Rat? Mache ich grundsätzlich was falsch?

    Danke schon mal 🙂

    Meiner



  • Grad gemerkt, dass in diesem Fall ADDR_ANY falsch ist. Es kommt dann der Fehler Code 10049. Wenn ich die IP vom Umsetzer eintrage, wird gesendet, aber es passiert weiter nichts.



  • Meiner schrieb:

    Grad gemerkt, dass in diesem Fall ADDR_ANY falsch ist. Es kommt dann der Fehler Code 10049. Wenn ich die IP vom Umsetzer eintrage, wird gesendet, aber es passiert weiter nichts.

    Wollte ich gerade anmerken. Du schreibst also addr.sin_addr.s_addr = inet_addr("destip"); ?

    Edit:
    Ich denke du musst zum Emfpangen deinen Socket an einen Port binden.



  • Jo, ich schreibe

    addr.sin_addr.s_addr    = inet_addr("129.247.49.232");
    

    Wenn ich was mit bind mache, dann funzt das Senden bekomme ich nur den Empfangsprozess hin (es kommt aber trotzdem nichts an) und des Sendevorgang nicht. Selbes Spiel nur ander rum^^.



  • Hier noch mal der Versuch über bind. Hier klappt aber das Senden nicht. Es wird Fehler 10057 gemeldet. Leider verstehe ich hierzu die Fehlerbeschreibung nicht so ganz.

    #include <winsock2.h>
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int startWinsock(void)
    {
        WSADATA wsa;
        return WSAStartup(MAKEWORD(2,0), &wsa);
    }
    
    int main()
    {
        long rc;
        SOCKET s;
        char buf[256];
        char buf2[300];
        SOCKADDR_IN addr;
        SOCKADDR_IN remoteAddr;
        int remoteAddrLen=sizeof(SOCKADDR_IN);
    
        rc=startWinsock();
    
        if(rc!=0)
        {
            printf("Fehler: startWinsock, fehler code: %d\n",rc);
            return 1;
        }
        else
        {
            printf("Winsock gestartet!\n");
        }
    
        s=socket(AF_INET,SOCK_DGRAM,0);
        if(s==INVALID_SOCKET)
        {
            printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
            return 1;
        }
        else
        {
            printf("UDP Socket erstellt!\n");
        }
        memset(&addr,0,sizeof(SOCKADDR_IN));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(2002);
        addr.sin_addr.s_addr=ADDR_ANY;
    
        rc=bind(s,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
        if(rc==SOCKET_ERROR)
        {
            printf("Fehler: bind, fehler code: %d\n",WSAGetLastError());
            return 1;
        }
        else
        {
            printf("Socket an Port 2002 gebunden\n");
        }
    
        /// Senden
        strcpy(buf2, "r");
        rc=sendto(s,buf2,strlen(buf2),0,0,0);
        if(rc==SOCKET_ERROR)
        {
          printf("Fehler: sendto, fehler code: %d\n",WSAGetLastError());
          return 1;
        }
        else
        {
          printf("%d Bytes gesendet!\n", rc);
        }
    
        /// Empfangen
        rc=recvfrom(s,buf,256,0,(SOCKADDR*)&remoteAddr,&remoteAddrLen);
        if(rc==SOCKET_ERROR)
        {
          printf("Fehler: recvfrom, fehler code: %d\n",WSAGetLastError());
          return 1;
        }
        else
        {
          printf("%d Bytes empfangen!\n", rc);
          buf[rc]='\0';
        }
        printf("Empfangene Daten: %s\n",buf);
    
        return 0;
    }
    


  • Woher soll sendto() denn wissen wohin es senden soll?



  • Könntest du das näher erläutern? Steh grad nen bisschen aufm Schlauch.

    Redest du vom 1. oder 2. Beispiel?



  • Vom Zweiten. Da rufst du sendto(s,buf2,strlen(buf2),0,0,0); auf. Woher soll sendto() jetzt wissen, wohin es die Daten senden soll? Du musst der Funktion schon eine Adresse mitgeben.

    Edit: Ungetestet, hatte ich hier noch rumfliegen. Vielleicht hilft es ja:

    // Edit, siehe weiter unten.
    


  • Danke, habs wie folgt geändert:

    rc=sendto(s,buf2,strlen(buf2),0,(SOCKADDR*)&addr, sizeof(SOCKADDR_IN));
    

    Da jetzt aber Fehler 10049 (Cannot assign requested address), scheint das auf jeden Fall nicht richtig zu sein.

    EDIT: Grad deinen Code gesehn, werds mal ausprobieren.

    EDIT2: Wenn ich das ADDR_ANY wieder mit inet_addr("destIP"); austausche (mit den oberen Änderungen), scheint bind nicht mehr zu funktionieren (10049). Probiere jetzt erstmal deinen Code aus.



  • Hast du meinen Code mal ausprobiert? Bei dir steht bei der Adresse immer noch INADDR_ANY, das solltest du ändern.

    Edit:
    Habe gerade dein Edit gesehen, hoffe mal es klappt. 😃



  • Also ums zum Laufen zu bekommen, habe ich folgendes eingefügt:

    #define WINSOCK_VERSION MAKEWORD(2,0)
    

    Dann hab ich noch die errorexit Funktion entfernt (Probleme beim Compilieren) und die Aufrufe durch Return 1 ersetzt. IP + Port habe ich auch angepasst. Nun öffnet sich einfach nen Fenster und es passiert nicht weiter. Anscheinend hängt er auch hier im Receive Prozess.



  • Das kann so alles nicht funktionieren, moment, ich versuche mal eben den alten Code aufzubesern. 🙂



  • Danke 🙂 . Kann doch eigetnlich alles nicht so schwierig sein. Es muss doch nur ein r am Gerät ankommen, alle Terminalprogramme könnens doch auch 😉 .



  • #include <stdlib.h>
    #include <stdio.h>
    #include <WinSock2.h>
    
    #pragma comment (lib, "Ws2_32.lib")
    
    void errorexit(const char *msg, ...)
    {
      va_list argv;
      va_start(argv, msg);
      vprintf(msg, argv);
      va_end(argv);
      getchar(); //blah, Windows ;)
      exit(-1);
    }
    
    int main()
    {
      char buf[0x100] = "r";
      int sock, rval;
      struct sockaddr_in addr = {0};
      WSADATA wsa;
    
      if (WSAStartup(WINSOCK_VERSION, &wsa) != 0)
        errorexit("WSAStartup() failed with: %i.", 
          WSAStartup(WINSOCK_VERSION, &wsa));
    
      addr.sin_addr.s_addr = INADDR_ANY;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(1911);
    
      if (!(sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
        errorexit("socket() failed with: %i.", WSAGetLastError());
    
      if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0)
        errorexit("bind() failed with: %i.", WSAGetLastError());
    
      memset(&addr, 0, sizeof(addr));
      addr.sin_addr.s_addr = inet_addr("192.168.0.127");
      addr.sin_family = AF_INET;
      addr.sin_port = htons(1911);
    
      if (sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&addr, sizeof(addr)) < strlen(buf))
        errorexit("sendto() failed with: %i.", WSAGetLastError());
    
      while ((rval = recv(sock, buf, sizeof(buf) - 1, 0)) > 0)
      {
        buf[rval] = '\0';
        printf("%s", buf);
      }
    
      closesocket(sock);
      WSACleanup();
      return 0;
    }
    

    So, das funktioniert auf jeden Fall lokal. (Gerade getestet.)



  • Funktioniert der Code bei dir so wie er oben steht? Ich bekomm nämmlich immer folgende Fehlermeldungen:

    |5|warning: ignoring #pragma comment |
    ||In function 'main':|
    |21|warning: missing initializer|
    |21|warning: (near initialization for 'addr.sin_port')|
    |24|error: 'WINSOCK_VERSION' undeclared (first use in this function)|
    |24|note: each undeclared identifier is reported only once for each function it appears in|
    sung.c|43|warning: comparison between signed and unsigned integer expressions|

    EDIT

    Wenn ich für WINSOCK_VERSION wieder was mit MAKEWORD(2,0) einfüge und als IP 127.0.0.1 einfüge, erscheint wenigstens das gesendete "r". Aber mit dem Gerät klappts immer noch nicht.



  • Jetzt sag mir nicht, dass du dev-cpp nutzt? 🙄

    Edit:
    Wie auch immer, #pragma comment() bindet nur die .lib ein, ist Compiler-spezifisch. WINSOCK_VERSION halt durch MAKEWORD(2,0) ersetzen.



  • Meiner schrieb:

    EDIT

    Wenn ich für WINSOCK_VERSION wieder was mit MAKEWORD(2,0) einfüge und als IP 127.0.0.1 einfüge, erscheint wenigstens das gesendete "r". Aber mit dem Gerät klappts immer noch nicht.

    Da muss die Ziel IP stehen, nicht deine. 🙂



  • CodeBlocks mit GCC.

    Mitm localhost war ja nur zum testen, ob überhaupt was passiert. Mit der richtigen DestIP wird immerhin das Programm komplett durchlaufen, es kommt nur keine Ausgabe der Zahl. Immerhin tut sich was 😃

    EDIT: Hatte doch noch nen kleinen Fehler drin, jetzt funktioniert es.



  • Meiner schrieb:

    EDIT: Hatte doch noch nen kleinen Fehler drin, jetzt funktioniert es.

    Wollte gerade fragen, ob du mir noch einmal deinen Code zeigen kannst. 🕶



  • Meiner? Is ja dein Code der funktioniert. Hatte vergessen beim zweiten Aufruf von htons den Port gegen den richtigen auszutauschen. Ansonsten hab ich nur

    #define WINSOCK_VERSION MAKEWORD(2,0)
    

    eingefügt.

    Aber kannst du mir erklären was du da jetzt genau machst? Warum legst du jetzt nochmal die komplette Adressstruktur fest, nachdem du bind aufgerufen hast, usw.
    Das scheint's ja zu sein, warum es nun geht.

    Du rufst bei bind mit sock auch einen Integer auf. Ich hab bislang immer nur gesehen, dass man die Variable als Typ SOCKET definiert (wies auch die Funktionsvorschrift fordert, oder? und nicht als Int. Macht das einen Unterschied?

    Aber schon mal vielen Dank für deine Hilfe 🙂 .


Anmelden zum Antworten