Ich verwende send() statt write(), die kein Signal verarbeiten :
bzero(buffer, MAX_SIZE_BUFFER);
n = read(sockfd, buffer, MAX_SIZE_BUFFER - 1);
printf("after read%d\n", n);
if (n <= 0)
{
break;
}
n2 = send(newsockfd, buffer, n, MSG_NOSIGNAL);
if (n2 == -1)
{
close(sockfd);
close(newsockfd);
return;
}
if (n2 != n)
{
break;
}
Die Socket-Programmierung kann ziemlich knifflig sein, da Sie oft erst viel später wissen, dass ein Fehler aufgetreten ist.
Wenn beispielsweise die Maschine, auf die Sie schreiben, abnormal heruntergefahren wird, kann der Schreibaufruf erfolgreich sein (weil Sie in Ihre internen Betriebssystempuffer schreiben konnten), nur um während des Schließaufrufs fehlzuschlagen.
Wenn Sie nicht auf Anwendungsebene überprüfen können, ob der Socket aktiv ist (dh eine Nachricht senden und innerhalb eines bestimmten Zeitraums eine Antwort erfordern), haben Sie keine Möglichkeit, dies zu wissen. Wenn Sie ein Standardprotokoll verwenden, ist möglicherweise bereits etwas vorhanden, um Fehler zu behandeln.
Die kurze Antwort lautet also, dass Sie bei so ziemlich jedem Aufruf, der den Socket berührt, nach Fehlerrückgaben suchen müssen (Lesen, Schreiben, Schließen usw.).
Um zu überprüfen, ob Sie in einen Socket schreiben können, versuchen Sie überraschenderweise, dorthin zu schreiben :-)
Wenn der Socket geschlossen wurde, erhalten Sie einen -1
Rückgabecode von write
und Sie können errno
untersuchen um zu sehen, was das Problem war.
Wenn der Socket noch gültig ist, aber Sie gerade keine Daten schreiben können, write
gibt 0 zurück. Der read
Aufruf verhält sich ebenfalls ähnlich und gibt -1
zurück wenn es ein Problem gibt.
Grundsätzlich für write
:
- wenn Sie einen
-1
zurückerhalten , ist ein Problem aufgetreten und Sie solltenerrno
überprüfen um zu sehen, ob es wiederherstellbar oder fatal ist. - Wenn Sie eine
0
zurückbekommen , dann können Sie im Moment nichts schreiben (kann ein Netzwerkrückstand oder ein anderes Problem sein, aber definitiv (noch) nicht schwerwiegend). - Wenn Sie einen geringeren Wert erhalten, als Sie wollten, dann etwas der Daten gesendet wurde. Passen Sie Ihre Zeiger an, damit Sie versuchen können, den Rest im nächsten Zyklus zu senden. nicht Angenommen, ein positiver Rückgabewert bedeutet, dass der gesamte Block gesendet wurde.
- Wenn Sie die gleiche Anzahl von Bytes zurückerhalten, die Sie versucht haben zu senden, wurde der gesamte Puffer zur Lieferung angenommen.
- Wenn Sie mehr zurückbekommen, als Sie angefordert haben, senden Sie eine E-Mail mit einem bissigen Kommentar an die Kernel-Entwickler. Linus und Co. werden das lieben :-)
Aktualisieren: Wie caf in den Kommentaren darauf hingewiesen hat, habe ich vergessen, die Signalbehandlung zu berücksichtigen. Sie müssen das Rohrbruchsignal oder write
ignorieren schlägt intern fehl, wenn dieses Signal angehoben wird.
Sie können dies tun, indem Sie Folgendes einfügen:
struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);
bevor Sie die Socket-Funktionen verwenden. Sie können dann verwenden:
sigaction (SIGPIPE, &old_actn, NULL);
um die vorherige Signalbehandlung wiederherzustellen.