wake-up-neo.com

Wie finde ich den Socket-Verbindungsstatus in C?

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?

25
Blacklabel

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));
}
33
Simone

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.

11
Chris Becke

Die TCP-Keepalive-Socket-Option (SO_KEEPALIVE) hilft in diesem Szenario und schließt den Server-Socket bei einem Verbindungsverlust.

4
blaze

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.

2
Parth Shah

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 =

1
Tal Bar

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.

1
chandank

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.

  1. Wenn der Socket nicht geschlossen ist und Daten zu lesen sind, gibt read mehr als Null zurück.
  2. Wenn am Socket keine neuen Daten vorhanden sind, wird POLLIN in revents auf 0 gesetzt.
  3. Wenn der Socket geschlossen ist, wird das Flag 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);
    }
}
1
yanpas