Ich habe eine TCP Verbindung. Server liest nur Daten vom Client. Wenn nun die Verbindung unterbrochen wird, wird der Client beim Schreiben der Daten in die Pipe (defekte Pipe) eine Fehlermeldung erhalten, aber Der Server hört immer noch auf dieser Pipe. Kann ich irgendwie herausfinden, ob die Verbindung aktiv ist oder nicht?
Sie könnten getsockopt wie folgt aufrufen:
int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len);
So testen Sie, ob der Socket aktiv ist:
if (retval != 0) {
/* there was a problem getting the error code */
fprintf(stderr, "error getting socket error code: %s\n", strerror(retval));
return;
}
if (error != 0) {
/* socket has a non zero error status */
fprintf(stderr, "socket error: %s\n", strerror(error));
}
Die einzige Möglichkeit, zuverlässig zu erkennen, ob ein Socket noch angeschlossen ist, besteht darin, regelmäßig zu versuchen, Daten zu senden. Normalerweise ist es bequemer, ein Ping-Paket auf Anwendungsebene zu definieren, das von den Clients ignoriert wird. Wenn das Protokoll jedoch bereits ohne eine solche Funktion ausgeführt wird, sollten Sie in der Lage sein, TCP-Sockets zu konfigurieren, indem Sie SO_KEEPALIVE Socket Option. Ich habe auf die Dokumentation zu Winsock verwiesen, aber auf allen BSD-ähnlichen Socket-Stacks sollte dieselbe Funktionalität verfügbar sein.
Die TCP-Keepalive-Socket-Option (SO_KEEPALIVE) hilft in diesem Szenario und schließt den Server-Socket bei einem Verbindungsverlust.
Ich hatte ein ähnliches Problem. Ich wollte wissen, ob der Server mit dem Client verbunden ist oder der Client mit dem Server verbunden ist. In solchen Fällen kann sich der Rückgabewert der Funktion recv als nützlich erweisen. Wenn der Socket nicht verbunden ist, werden 0 Bytes zurückgegeben. Mit diesem Befehl habe ich die Schleife durchbrochen und musste keine zusätzlichen Funktionsthreads verwenden. Sie können dies auch verwenden, wenn Experten der Meinung sind, dass dies die richtige Methode ist.
Sie sollten versuchen, getpeername zu verwenden.
wenn die Verbindung unterbrochen ist, wird folgende Fehlermeldung angezeigt: ENOTCONN - Die Steckdose ist nicht angeschlossen. das heißt für dich DOWN.
sonst (wenn keine anderen Fehler vorliegen) wird der Rückgabewert 0 -> was UP bedeutet.
Ressourcen: Manpage: http://man7.org/linux/man-pages/man2/getpeername.2.html =
get sock opt kann etwas nützlich sein, eine andere Möglichkeit wäre jedoch, einen Signal-Handler für SIGPIPE zu installieren. Grundsätzlich sendet der Kernel jedes Mal, wenn die Socket-Verbindung unterbrochen wird, ein SIGPIPE-Signal an den Prozess, und Sie können dann die erforderlichen Aktionen ausführen. Dies ist jedoch immer noch keine Lösung, um den Status der Verbindung zu ermitteln. hoffe das hilft.
Es gibt eine einfache Möglichkeit, den Socket-Verbindungsstatus über den Aufruf poll
zu überprüfen. Zuerst müssen Sie Socket abfragen, ob es ein POLLIN
-Ereignis hat.
read
mehr als Null zurück.POLLIN
in revents
auf 0 gesetzt.POLLIN
auf eins gesetzt und read gibt 0 zurück.Hier ist ein kleines Code-Snippet:
int client_socket_1, client_socket_2;
if ((client_socket_1 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s1");
abort();
}
if ((client_socket_2 = accept(listen_socket, NULL, NULL)) < 0)
{
perror("Unable to accept s2");
abort();
}
pollfd pfd[]={{client_socket_1,POLLIN,0},{client_socket_2,POLLIN,0}};
char sock_buf[1024];
while (true)
{
poll(pfd,2,5);
if (pfd[0].revents & POLLIN)
{
int sock_readden = read(client_socket_1, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_2, sock_buf, sock_readden);
}
if (pfd[1].revents & POLLIN)
{
int sock_readden = read(client_socket_2, sock_buf, sizeof(sock_buf));
if (sock_readden == 0)
break;
if (sock_readden > 0)
write(client_socket_1, sock_buf, sock_readden);
}
}