Ich benutze Recv auf einer grundlegenden TCP-Verbindung. Dies ist der [] Byte, das lese ich gerade: [0 4 9 0]Recv() überspringt Bytes
Hier sind die recv Anrufe und am Ende des Code im Kontext
recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL);
len = ntohs(len);
recv(fd_serv, &tool_id, sizeof (tool_id), MSG_NOSIGNAL);
recv(fd_serv, rdbuf, len, MSG_NOSIGNAL);
Wenn in gdb debuggen ich sehen kann, dass
len = 4
tool_id = 9
rdbuf = [ 0 4 9 0 ]/[ 0 4 \t 0 ]
Wie ist das möglich? Es sieht so aus, als ob RECV die ersten zwei Bytes für len und das nächste Byte für tool_id (wie die Länge/Größe) nimmt, während alle Bytes für rdbuf genommen werden. Ich würde erwarten, dass es konsistent ist. Ich dachte, dies könnte ein Feature für das Lesen von Teilbyte sein, aber anscheinend liege ich falsch.
Wenn ich
recv(fd_serv, &tool_id, sizeof (tool_id), MSG_NOSIGNAL);
aus dem Code und überprüfen RDBUF in gdb die ersten 2 Byte entfernen Änderung nach
recv(fd_serv, rdbuf, len, MSG_NOSIGNAL);
Ausführung wird es
[ 9 0 9 0 ]/[ \t 0 \t 0 ]
Als ich es wieder Kommentar- , das Rdbuf ist wieder normal. Zuerst dachte ich, dass die übriggebliebenen Bytes, die nicht gelesen wurden, kopiert werden. Ich habe rdbuf [3] auf 5 gesetzt und dachte, es könnte 0 dann ersetzen, aber das tat es nicht. Von jetzt an bin ich ratlos, was hier passiert und warum es hier widersprüchlich ist.
Ich bin mit Arch Linux x86_64 gdb 7.12.1, gcc 6.3.1 und diese zu bauen:
gcc -g -DDEBUG *.c -o client.dbg -lcrypto
Kontext
while(TRUE) {
if (fd_serv != -1 && FD_ISSET(fd_serv, &fdsetrd)) {
int n;
uint16_t len;
uint8_t tool_id;
char rdbuf[1024];
errno = 0;
n = recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL | MSG_PEEK);
if (n == -1) {
if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
continue;
else
n = 0;
}
if (n == 0) {
close_connection();
continue;
}
if (len == 0) {
recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL);
continue;
}
len = ntohs(len);
if (len > sizeof (rdbuf)) {
close(fd_serv);
fd_serv = -1;
}
errno = 0;
n = recv(fd_serv, rdbuf, len, MSG_NOSIGNAL | MSG_PEEK);
if (n == -1) {
if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
continue;
else
n = 0;
}
if (n == 0) {
close_connection();
continue;
}
recv(fd_serv, &len, sizeof (len), MSG_NOSIGNAL);
len = ntohs(len);
recv(fd_serv, &tool_id, sizeof (tool_id), MSG_NOSIGNAL);
recv(fd_serv, rdbuf, len, MSG_NOSIGNAL);
printf("%d\n", tool_id);
}
}
Sie müssen immer den Rückgabewert von 'recv()' überprüfen. Es sagt Ihnen nicht nur über Fehler, aber es sagt Ihnen, wie viele Bytes tatsächlich von dem Aufruf zurückgegeben wurden. –