recv liefert 0, trotz empfangener Daten
-
Hallo,
ich versuche schon mehrere Abende folgendes Problem zu lösen:
Über eine TCP/IP-Vebindung soll ein Windows-Client (in Visualbasic geschrieben)
mit einem Linux-Server (in C++ geschrieben) Ascii-Daten austauschen.Der read- bzw. recv-Befehl empfängt zwar die Daten, jedoch liefert er als Anzahl
der empfangenen Zeichen 0.
Mit dem nichtblockierenden select-Befehl bekomme ich gar keine Daten.Folgende Meldung bekomme ich auf dem Server, wenn ich "hallo echo" sende.
You got a connection from 10.210.50.110
0 Zeichen: hallo echoKennt hier jemand die Lösung?
Danke und Grüsse
UlliAuzug aus dem Quelltext des Linux-Servers:
int main() { int fd; /* file descriptor */ char message[512]; int bytes; struct sockaddr_in server; /* server's address information */ struct sockaddr_in client; /* client's address information */ uint sin_size; if ((fd=socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ /* calls socket() */ printf("socket() error\n"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(PORT_SETTING); server.sin_addr.s_addr = INADDR_ANY; bzero(&(server.sin_zero),8); if(bind(fd,(struct sockaddr*)&server,sizeof(struct sockaddr))==-1){ printf("bind() schlägt fehl\n"); exit(-1); } if(listen(fd,BACKLOG) == -1){ printf("listen() schlägt fehl\n"); exit(-1); } while(1){ sin_size=sizeof(struct sockaddr_in); if ((fd = accept(fd,(struct sockaddr *)&client,&sin_size))==-1){ printf("accept() schlägt fehl\n"); exit(-1); } printf("You got a connection from %s\n",inet_ntoa(client.sin_addr) ); if (bytes = recv( fd, message, 512, 0 )==-1) printf("Fehler im Telegramm\n"); // message[bytes] = '\0'; printf("%d Zeichen: %s\n", bytes, message); } close(fd); }
Auzug aus dem Quelltext des Windows-Client:
Private Sub btnSenden_Click() tcpClient.SendData ("hallo echo" & vbCrLf) End Sub
-
Das Problem ist folgende Zeile
if (bytes = recv( fd, message, 512, 0 )==-1)
Das ist äquivalent zu
bool b=recv(fd, message, 512, 0) == -1; if (bytes = b)
Was du meinst ist aber
ssize_t bytes=recv(fd, message, 512, 0); if (bytes == -1)
du musst also eine Klammer setzen
if ((bytes = recv( fd, message, 512, 0 ))==-1)
Oder einfach die Ausdrücke ein wenig entzerren, macht den Code leserlicher und dadurch weniger Fehleranfällig. Ich halte nicht so viel davon möglichst alles in eine Zeile zu packen.
HTH
btw. enthält dein Code einen weiteren Fehler.
Entweder musst du die Zeile message[bytes]='\0' entkommentieren, da sonst der String nicht terminiert wird. Wenn du die Zeile aber einsetzt, dann schreibst du über die Speichergrenze, wenn jemand 512 Bytes schickt
-
if (bytes = recv( fd, message, 512, 0 )==-1)
Du beachtest die Operatorenreihenfolge nicht, == bindet stärker als =. Dein Ausdruck ist also äquivalent zu
bytes = (recv(...) == -1);
und das ist, wenn kein Fehler vorliegt, false, also 0.
-
... doofer Fehler!
... schon korrigiert.
-
Hallo Leute,
ich will ja nicht nerven, aber jetzt knoble ich schon wieder an einem Problem mit den Sockets:
Dieses Mal ist´s der Befehl select().
Obwohl ich zu dem Socket Daten schicke, (die ich auch testweise mit recv Dank Eurer Hilfe auslesen kann) reagiert select nicht. Die Stelle ist im Sourcecode als Übersicht enthalten.Ich vermute mal der Fehler ist dieses Mal wieder recht doof, aber ich habe schon in diversen Tutorials und Foren dazu nachgelesen, ohne Erfolg.
Danke
UlliDazu folgender Auszug aus dem Sourcecode:
int socket_settings; fd_set rfds; struct timeval tv; int retval; FD_ZERO(&rfds); FD_SET(socket_settings, &rfds); while(1){ ssize_t bytes; char udp_message[512]; tv.tv_sec = 5; tv.tv_usec = 0; retval = select((socket_settings), &rfds, NULL, NULL, &tv); if (retval) printf("Data is available now.\n"); else printf("No data within five seconds.\n"); /* bytes = recv( socket_settings, udp_message, 512, 0 ); if (bytes ==-1) printf("Fehler im UDP-Telegramm\n"); udp_message[bytes] = '\0'; printf("%d Zeichen: %s\n", bytes, udp_message); */ }
-
// ... retval = select(socket_settings +1, &rfds, NULL, NULL, &tv); // ...
mfg
-
Hallo terraner,
in der ursprünglichen Version hatte ich "socket_settings +1".
Durch die viele Probiererei bei der Fehlersuche hatte ich diesen falschen
Quellcode kopiert.Ich hab´s gerade noch einmal mit
retval = select(socket_settings +1, &rfds, NULL, NULL, &tv); if (retval) printf("Data is available now.\n"); else printf("No data within five seconds.\n");
ausprobiert, leider ohnen Erfolg.
Hat Du noch eine andere Idee?
Ulli
-
Hallo,
ich habe noch einmal etwas herumprobiert (try and error)
Einmal hat der Server Daten empfangen, doch leider danach nicht mehr.Kann es sein, dass die Daten im Empfangspuffer nicht solange (ca 0,5 bis 1 sec) gespeichert werden?
... oder liegt es daran, dass ich UDP benutze?socket_settings=socket(AF_INET, SOCK_DGRAM, 0)
Danke
Ulli
-
Hallo,
ich bin´s noch einmal:wenn ich FZERO ... und FD_SET ... in die Schleife setze
funktioniert es.hiermit wird doch nur die Gruppe der zu beobachteten Desrcriptoren definiert,
Warum muss das vor jedem select geschehen?Danke für die Hilfe
Ullifd_set rfds; struct timeval tv; while(1){ FD_ZERO(&rfds); FD_SET(socket_settings, &rfds); int retval; ssize_t bytes; char udp_message[512]; /***************** select auf UDP-Socket********************/ /* Watch stdin (fd 0) to see when it has input. */ /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; retval = select(socket_settings +1, &rfds, NULL, NULL, &tv); if (retval){ bytes = recv( socket_settings, udp_message, 512, 0 ); if (bytes ==-1) printf("Fehler im UDP-Telegramm\n"); udp_message[bytes] = '\0'; printf("%d Zeichen: %s\n", bytes, udp_message); }else printf("-> keine Daten in 5 Sekunden von Port %d empfangen!\n", PORT_SETTING); }