Probleme mit SOCKETS und UDP
-
Hallo,
ich möchte endlich mal richtig mit Sockets arbeiten, aber natürlich mit UDP denn
TCP/IP kann ich für Spiele absolut nicht gebrauchen weil das ja zu langsam ist.Ich hab mir schon einige Beispiele angesehen und verstehe zum Teil schon mal das Grundprinzip.
Allerdings kommt bei meinem SocketTest keine Nachricht mehr zurück wenn ich UDP verwende.// Mit TCP/IP mache ich das so: SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Mit UDP mache ich das so: SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);Das müsste schon mal soweit richtig sein oder?!
// Das hab ich aus einem Tutorial, funktioniert auch mit TCP/IP wenn ich das an "192.168.2.1" (mein Router) schicke char msg[1024] = "GET / HTTP/1.1\r\nHost: www.example.net\r\n\r\n"; // Result ist bei UDP leider immer -1 int result = recv(sock, msg, sizeof(msg) - 1, 0);Wenn euch das an Code nicht reicht, hier ist noch mal der ganze Code:
#include <cstdio> #include <cstdlib> // für exit() #include <unistd.h> // für close() #include <string> // für memset() #include <winsock2.h> using namespace std; int main(void) { WSADATA wsa; int result; // starting winsock result = WSAStartup(0x0002, &wsa); // 0x0002 for Windows 2.0, 0x0101 for Win 1.1 if (result) { // WinSock API error handling printf("Error: WSAStartup, "); switch(result) { case WSASYSNOTREADY: printf("WinSock not ready\n"); break; case WSAVERNOTSUPPORTED: printf("requested WinSock version not supported\n"); break; case WSAEINPROGRESS: printf("blocking WinSock 1.1 operation in progress\n"); break; case WSAEPROCLIM: printf("maximum WinSock tasks reached\n"); break; case WSAEFAULT: printf("The lpWSAData is not a valid pointer\n"); break; default: printf("Unknown error code: %d\n", result); break; } return result; } // main rutine SOCKET sock; // wir holen uns den descriptor für einen socket (soll mal TCP/IP werden) // int socket(int domain { AF_INET, PF_INET, PF_INET6, PF_IPX, PF_PACKET } , int type { SOCK_DGRAM, SOCK_STREAM } , int protocol ); // !!! Hier ist TCP/IP und UDP !!! #if 1 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); // UDP #else sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // TCP/IP #endif if (sock == -1 ) { perror("could not create socket\n"); system("PAUSE"); exit(1); } else printf("create socket successful\n"); // Strukur anlegen, mit Nullen füllen und initialisieren sockaddr_in dest_addr; memset(&dest_addr, 0, sizeof(dest_addr)); // alles mit Nullen füllen dest_addr.sin_family = AF_INET; // muss hier nochmal stehen dest_addr.sin_port = htons(80); // auf dem Port läuft meistens HTTP dest_addr.sin_addr.s_addr = inet_addr("192.168.2.1"); // IP Addresse von www.example.net // verbinden if (connect(sock, (sockaddr*)&dest_addr, sizeof(sockaddr)) == -1) { perror("could not connet to 192.168.2.1:80\n"); system("PAUSE"); exit(2); } else printf("connection successful\n"); // eine Nachricht senden char msg[1024] = "GET / HTTP/1.1\r\nHost: www.example.net\r\n\r\n"; // blockierende Funktion (wartet bis alle Daten gesendet wurden) result = send(sock, msg, strlen(msg), 0); if (result == -1) { perror("couldn't send data"); system("PAUSE"); exit(3); } if (result < (signed)strlen(msg)) { // eigentlich kein Fehler, aber für diese Zwecke lassen wir es einen sein perror("couldn't send all data"); system("PAUSE"); exit(4); } do { // blockierende Funktion, wartet solange bis eine Antwort kommt (Daten, Fehler, Verbindung beendet) result = recv(sock, msg, sizeof(msg)-1, 0); if (result == 0) { puts("\r\nconnection terminated by server\n"); break; } else if (result == -1) { perror("recv() error"); //system("PAUSE"); //exit(5); result = 1; } else { msg[result] = 0; // string terminieren puts(msg); } } while (result > 0); // close socket close(sock); WSACleanup(); system("PAUSE"); return EXIT_SUCCESS; }Kann mir jemand sagen was ich falsch mache oder was da noch fehlt?
Danke schon mal

-
LukasBanana schrieb:
ich möchte endlich mal richtig mit Sockets arbeiten, aber natürlich mit UDP denn
TCP/IP kann ich für Spiele absolut nicht gebrauchen weil das ja zu langsam ist.Absoluter Quark!
Es kommt ganz auf das Spiel und die Menge an Daten an. UDP wird aber oft gewählt, weil es in Netzwerken und bei Firewalls einige Vorteile bietet. Der zusätzliche Overhead von TCP fällt selten wirklich ins Gewicht. TCP ist allerdings deutlich leichter zu benutzen als UDP.Ob der Code funktioniert oder nicht, kann ich nicht gleich sagen, nur was mich stutzig macht, ist die HTTP Anweisung mit UDP. Soweit ich weiss geht HTTP nur über TCP, weshalb dein Router wahrscheinlich nicht antwortet.
Im übrigen übermittelst du jede Menge Schrott, welcher wahrscheinlich auch noch Probleme macht. Du übermittelst 1023 Zeichen, wovon du aber nur eine ganz kleine Anzahl benutzt. Den Rest lässt du auf einem uninitialisierten Zustand, wodurch irgendwelche Zeichen übermittelt werden. Das kann ja fast nicht gut gehen.
Und noch was fällt mir auf. Mit UDP und Winsock braucht man doch andere send und receive Funktionen. War doch sowas wie send_to und receive_from. Dafür fiel doch das connect weg. Irgendwas in der Art, am besten machst du mal ein Tutorial zu Winsocks durch.
http://www.c-worker.ch/tuts/udp.php
Ist zwar für C, aber wieso nicht.Und falls du eine API haben möchtest, welche in C++ ist und Platformunabhängig, wäre noch Boost.Asio zu empfehlen

Grüssli
-
Wenn es eh ein Spiel werden soll, kann man sich natürlich auch SDL in Verbindung mit SDL_net anschauen. Oder Qt verwenden etc. pp.
-
Noch was ist mir in den Sinn gekommen, das editier ich jetzt nicht rein, da Fellhuhn schon geantwortet hat. Du bist im falschen Forum!
Winsockets ist WinAPI und somit:
http://www.c-plusplus.net/forum/viewforum-var-f-is-4.htmlGrüssli
-
Danke schön Dravere

Das Tutorial sieht schon mal sehr hilfreich aus
-
Aber noch mal ne kurze Frage - (ich will dafür jetzt nicht extra noch mal einen Thread aufmachen):
ist die Funktion recvfrom auch einen blokierende Funktion?
Das wäre nämlich sau unpraktisch
Wenn das Programm nämlich gerade eine Nachricht empfangen will, aber es kommt keine mehr, hängt sich das Programm auf.
-
LukasBanana schrieb:
ist die Funktion recvfrom auch einen blokierende Funktion?
Das weiss ich auch nicht, wir sind ja nicht im WinAPI Forum. Aber das könntest du auch selber in der MSDN nachschlagen:
MSDN: recvfrom
Da steht:If no incoming data is available at the socket, the recvfrom function blocks and waits for data to arrive according to the blocking rules defined for WSARecv with the MSG_PARTIAL flag not set unless the socket is nonblocking.
LukasBanana schrieb:
Das wäre nämlich sau unpraktisch

Wenn das Programm nämlich gerade eine Nachricht empfangen will, aber es kommt keine mehr, hängt sich das Programm auf.Deshalb lagert man eigentlich oft solche Sachen in Threads aus. Die recv Funktion ist übrigens auch blockierend, kannst du auch in der MSDN nachlesen

Grüssli