Asci Zeichen per UDP senden



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



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


Anmelden zum Antworten