Asci Zeichen per UDP senden



  • 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 🙂 .



  • Na bis bind() dürfte doch alles klar sein? Danach schreibe ich die ganze Struktur nur noch mal neu, weil ich bind() ja die Adresse von addr mitgebe, die Funktion könnte theretisch ja sonst was da rein schreiben. Eigentlich hätte man nur die IP ändern müssen, aber da ich viel zu faul bin um nachzugucken was da jetzt wo garantiert wird, schreibe ich halt einfach alles neu. 🙂

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

    Das ist nur ein hilfloser Versuch das Ganze irgendwie systemunabhängiger zu machen, nutze ruhig SOCKET, das ist besser.



  • Wozu ist das bind() denn jetzt gut, wenn du danach eh alles neu definierst und es für sendto() und recv() dann gar keine Rolle mehr spielt? Du hebst doch die vorher festgelegt "Bindung" mit der neuen Struktur direkt wieder auf, oder nicht? Bin grad nen bisschen verwirrt 😕 .



  • Ne. Wenn du etwas empfangen willst, egal ob mit recv() oder recvfrom() (die letzten Parameter sagen recvfrom() nicht von wo es empfangen soll, sondern recvfrom() speichert hier von wo empfangen wurde(!)) muss das Betriebssystem ja wissen, dass dein Socket an einem bestimmten Port auf etwas wartet. Und mit bind() machst du ihm das bekannt. Der Funktion bind() ist es auch egal, was du nachher mit der SOCKADDR_IN machst, die hat die Daten schon ans System weitergegeben.
    Siehe auch http://msdn.microsoft.com/en-us/library/ms737550(v=vs.85).aspx

    Edit:
    (connect() könnte hier eigentlich auch funktionieren, bzw. bei z.B. TCP-Sockets funktioniert das auf jeden Fall. Aber auch da kannst du immer erst nach bind() oder connect() etwas empfangen.

    Edit: Funktioniert genauso gut. 🙄

    #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));
    
      if (!(sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
        errorexit("socket() failed with: %i.", WSAGetLastError());
    
      addr.sin_addr.s_addr = inet_addr("192.168.0.127");
      addr.sin_family = AF_INET;
      addr.sin_port = htons(1911);
    
      if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0)
        errorexit("connect() failed with: %i.", WSAGetLastError());
    
      if (send(sock, buf, strlen(buf), 0) < strlen(buf))
        errorexit("send() 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;
    }
    


  • mhh, also greift die recv() Funktion noch auf die Daten zu, die mit bind festgelegt wurde, obwohl vor dem eigentlichen recv() Aufruf diese Daten nochmals verändert wurden?
    Würde das Beispiel auch funktionieren, wenn ich bei der zweiten Strukturfestlegung alle Daten inkl. Port ändern würde?

    EDIT: Ich hab gelesen, dass recv() und recvfrom() einen bind implizieren. Ist das der Grund, warum es nun auch ohne bind() geht?

    Wenn ich allerdings auf unterschiedlichen Ports senden und empfangen möchte, brauche ich dann zwingend bind()?



  • Meiner schrieb:

    mhh, also greift die recv() Funktion noch auf die Daten zu, die mit bind festgelegt wurde, obwohl vor dem eigentlichen recv() Aufruf diese Daten nochmals verändert wurden?
    Würde das Beispiel auch funktionieren, wenn ich bei der zweiten Strukturfestlegung alle Daten inkl. Port ändern würde?

    Ja. Aber nutze einfach connect(), das sollte einfacher sein.



  • connect() legt im Falle von UDP ja den Standard Zielrechner fest.
    Wenn ich dann an einen Anderen etwas senden, oder von einem Anderen etwas empfangen möchste, muss ich die Struktur wieder entsprechend ändern und dann rec() oder sendto(), etc. aufrufen, richtig?
    Im Prinzip ist dann zwischen bind() und connect() (bei UDP) eigentlich kein Unterschied.

    Wenn das stimmt, dann versteh ich es langsam.



  • Um mal die Überschriftfrage zu beantworten (alles andere gehört nach WinAPI):

    Nein, du kannst keine ASCII Zeichen per UDP senden, du kannst Bytefolgen per UDP senden/empfangen, die du auf beiden Seiten u.a. als ASCII interpretieren kannst.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum C (C89 und C99) 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.



  • Also mit der Hilfe von cooky451, funktioniert die bind() Methode sehr gut. Allerdings benutze ich hier immer

    addr.sin_addr.s_addr    = INADDR_ANY;
    

    , wies ja auch von cooky451 benutzt wurde.

    Da ich aber nur von einer bestimmten IP Adresse empfangen möchte, habe ich mal die IP von meinem Umsetzter eingetragen. Dies hat aber den Effekt, dass das Programm wieder beim Empfangen hängen bleibt.

    Selbes Phänomen bei der connect() Methode. Der Code von cooky451 hierzu funktioniert ebenso wenig wie meine "Eigenkreationen".

    Anscheinend ist immer INADDR_ANY nötig, um etwas zu empfangen. Aber woran kann das liegen? Das Gerät sendet doch nicht plötzlich über eine andere IP 😕

    @rüdiger: Danke fürs Verschieben. Habe übersehen, dass mein Problem eher zu WinAPI gehört.

    @Wutz: Danke, aber das war mir eigentlich klar. Ich wollte ja mit meiner Frage auf etwas anderes hinaus. Die Überschrift ist wohl nen bisschen schlecht gewählt.


Anmelden zum Antworten