C++: Udp mit select() & Timeout
-
Dieser Thread wurde von Moderator/in nman aus dem Forum Linux/Unix 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.
-
keiner der mir helfen kann?
oder ist meine frage unklar?
-
Was gibt recvfrom denn zurück?
-
mit WSAStartup (MAKEWORD (2,2), &wsa):
in der allerersten Schleife meldet select()korrekt einen Timeout, danach nicht mehr und recvfrom() liefert 4lachende Smileys gefolgt von "WinSock 2.0" (das mit den Smileys ist kein Witz !mit WSAStartup (MAKEWORD (2,0), &wsa):
Das gleiche Verhalten, allerdings nur ein einzelnes Smiley, sonst nix
-
Was gibt recvfrom denn zurück?
-
sry
recvfrom: -1
WSAGetLastError: 10054
-
moon12 schrieb:
recvfrom: -1
Also ein Fehler. Dann solltest du nichts ausgeben, da kann ja nur Quark kommen.
moon12 schrieb:
WSAGetLastError: 10054
Doku sagt:
WSAECONNRESET: On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.
-
das da mist rauskommt ist ja klar, mein programm hat ja auch nichts empfangen sondern nur selbst gesendet.
Meine Frage war ja auch, warum select() zuvor keinen Timeout meldet, sondern eben eine 0, was überhaupt erst dazu führt, dass recvfrom() aufgerufen wird.und was das WSAECONNRESET betrifft:
Was genau bedeutet das? nach meinem bisherigen verständnis ist doch udp verbindungslos, also wird eine nachricht einfach an einen Port gefeuert und danach sich nicht mehr drum gekümmert oder nicht? wie sollte das also mein select() beeinflussen?
-
Wsa gibt denn sendto zurück?
-
56
also die Anzahl an gesendeten Bytes
WSAGETLASTERROR bei sendto: 0
-
Ok, ich kann es reproduzieren, aber erklären kann ich's nicht.
-
hm immerhin ^^
aber ist mein ansatz sonst (mit ausnahme, dass ich an localhost sende) in ordnung?
oder würde man senden & empfangen in dem verbund generell anders realisieren?
-
Nutz beim Initialisieren mal Winsock 2.0
Mach den ersten Parameter bei select zu 0 (der wird unter Windows nicht benötigt)Ist dein Puffer groß genug?
Und dann mach mal ein kompilierbares Beispiel, ansonsten hab ich keine Lust mir das genauer anzuschauen...
-
frisch aufgesetzt:
// Udp: senden->empfangen per select() # pragma comment(lib, "Ws2_32.lib") # include <string> # include <iostream> # include <WinSock2.h> # include <Windows.h> using namespace std; int main() { //--Variablenliste int iRemoteAddrLenght = sizeof(SOCKADDR_IN); long rc; SOCKET UdpSocket; char szBuffer[256] = {0}; SOCKADDR_IN RemoteAddr; SOCKADDR_IN OwnAddr; fd_set Fds; struct timeval Timeout; Timeout.tv_sec = 2; Timeout.tv_usec = 0; string sSend = "Teststring"; string sRecv; //--Winsock WSADATA wsa; rc = WSAStartup (MAKEWORD (2,0), &wsa); if (rc != 0) { cout << "Fehler: startWinsock, Fehlercode: " << rc << endl; } //if else { cout << "Winsock gestartet!" << endl; } //else //--Socket UdpSocket = socket(AF_INET, SOCK_DGRAM, 0); if (UdpSocket == INVALID_SOCKET) { cout << "Fehler: Socket konnte nicht erstellt werden, Fehlercode: " << WSAGetLastError() << endl; } //if else { cout << "Socket erstellt!" << endl; } //else //--SOCKADDR_IN RemoteAddr.sin_family = AF_INET; RemoteAddr.sin_port = htons (2002); RemoteAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); OwnAddr.sin_family = AF_INET; OwnAddr.sin_port = htons (2003); OwnAddr.sin_addr.s_addr = ADDR_ANY; //--bind: OwnAddr rc = bind(UdpSocket, (SOCKADDR*) &OwnAddr, sizeof(OwnAddr)); if (rc == SOCKET_ERROR) { cout << "Fehler: bind, Fehlercode: " << WSAGetLastError() << endl; } //if else { cout << "Socket an Port " << htons(OwnAddr.sin_port) << " gebunden!" << endl; } //else //--Endlosschleife mit senden + empfangen for(;;) { //--sendto rc = sendto(UdpSocket, sSend.c_str(), strlen(sSend.c_str()), 0 , (SOCKADDR*) &RemoteAddr, sizeof(RemoteAddr)); cout << "return sendto: " << rc << endl; if (rc == SOCKET_ERROR) { cout << "Fehler: sendto, Fehlercode: " << WSAGetLastError() << endl; } //if else { cout << "sendto, gesendet: " << sSend << endl; cout << rc << " Bytes gesendet!" << endl; } //else //--select FD_ZERO(&Fds); FD_SET(UdpSocket,&Fds); rc = select(0, &Fds, NULL,NULL, &Timeout); cout << "return select: " << rc << endl; if(rc == -1) { cout << "Fehler: select, Fehlercode: " << WSAGetLastError() << endl; } //if else if(rc == 0) { cout << "Fehler: select timeout" << endl; cout << "select timeout Fehlercode: " << WSAGetLastError() << endl; } //else if else if(rc > 0) { if(FD_ISSET(UdpSocket, &Fds)) { rc = recvfrom(UdpSocket, szBuffer, 256, 0, (SOCKADDR*) &RemoteAddr, &iRemoteAddrLenght); cout << "return recvfrom: " << rc << endl; if (rc == SOCKET_ERROR) { cout << "Fehler: recvfrom, Fehlercode: " << WSAGetLastError() << endl; } //if else { sRecv = szBuffer; cout << " Empfangen: " << sRecv << endl; cout << rc << " Bytes empfangen!" << endl; } //else } //if } //else if cout << endl << "----------------------------------------" << endl; } //for closesocket(UdpSocket); WSACleanup(); return 0; } //main()
Wobei ich rausgefunden habe, dass das Problem immer auftritt, wenn ich den Socket auf der Gegenseite nicht eingerichtet habe, egal bei welcher Ip im Netzwerk.
-
Lang ists her...
Die Lösung ist:
select() verändert die Einstellungen bei jedem Durchlauf.
Man muss das
Timeout.tv_sec = 2;
Timeout.tv_usec = 0;innerhalb der Endlosschleife neu setzen.
Dank, natürlich, an Stackoverflow.