socket, détecter la connexion est perdue
Je me connecte à un serveur de processus et un processus client avec une connexion TCP, et j'ai pour détecter
que la connexion physique entre les deux machines est en baisse. Je suis en train de le faire à l'aide de la keepalive,
la diminution de la valeur par défaut à l'échelle du système des valeurs:
TCP_KEEPIDLE=5
TCP_KEEPCNT = 5
TCP_KEEPINTVL = 1
Lors de la panne ( j'ai débrancher le câble ), seul le serveur en 10 secondes détecter que la connexion a été perdue, le client se bloque sur le envoyer.
C'est le code de client:
#include <iostream>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/tcp.h>
int main(int argc, char** argv) {
char myVector[1600];
int mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (mySocket < 0 ) {
std::cout << "error creating the socket" << strerror(errno) << std::endl;
::exit(-1);
}
struct sockaddr_in sin;
memset( (char *)&sin, 0, sizeof( sin ) );
sin.sin_addr.s_addr = inet_addr("192.168.21.27");
sin.sin_port = htons(7788);
sin.sin_family = AF_INET;
if ( connect( mySocket, (struct sockaddr *)&sin, sizeof( sin )) < 0 ) {
std::cout << "Error on connection: " << strerror(errno) << std::endl;
::exit(-1);
}
int optval = 1;
socklen_t optlen = sizeof(optval);
/*Enabling keep alive*/
if(setsockopt(mySocket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
std::cout << "Error setting SO_KEEPALIVE: " << strerror(errno) << std::endl;
}
optval = 5;
optlen = sizeof(optval);
if(setsockopt(mySocket, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) {
std::cout << "Error setting TCP_KEEPIDLE: " << strerror(errno) << std::endl;
}
optval = 5;
optlen = sizeof(optval);
if(setsockopt(mySocket, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) {
std::cout << "Error setting TCP_KEEPCNT: " << strerror(errno) << std::endl;
}
optval = 1;
optlen = sizeof(optval);
if(setsockopt(mySocket, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) {
std::cout << "Error setting TCP_KEEPINTVL: " << strerror(errno) << std::endl;
}
for (;;) {
ssize_t myRet= ::send(mySocket,
myVector,
sizeof(myVector),
0);
if (myRet < 0) {
std::cout << "Error: " << strerror(errno) << std::endl;
break;
}
std::cout << myRet << "."; std::cout.flush();
sleep(1);
}
}
Je suis sûr que je suis absent quelque chose, mais quoi ?
OriginalL'auteur Gaetano Mendola | 2010-12-03
Vous devez vous connecter pour publier un commentaire.
TCP Keepalive n'est pas prévu pour cet usage.
Si vous voulez détecter les pannes au niveau de la couche application, faire ce que les protocoles SSH, IMAP et IRC n' - mettre en œuvre une echo/ping type de message à la couche application. Les envoyer sur une base régulière, et si vous n'obtenez pas une réponse en temps opportun, la connexion peut être supposé être à la baisse.
Il permet à long terme obsolète connexions éventuellement détectée et effacé - les cas où l'actualité n'est pas important.
OriginalL'auteur caf
Nous nous sommes interrogés sur cette question dans notre société il y a un moment : "comment faire pour détecter la connexion est allé vers le bas?".
Pour régler ce problème de manière fiable, nous avons dû mettre en œuvre un "battements de coeur" du système, c'est à dire le client de vérifier régulièrement (chaque seconde dans notre cas) que le serveur est toujours là, en faisant une pseudo-ping.
Si vous ne voulez pas le faire, vous pouvez attendre que l'OS fait détecte que la connexion est allé vers le bas, mais ne vous attendez pas à être fiable...
OriginalL'auteur Mikarnage
Donc,
après plus de investigaion, même si "TCP Keepalive" n'est pas prévu pour cet usage, j'ai découvert que la garder vivante sondes ont commencé à être envoyés sur une "connexion inactive". La question est maintenant: "lorsqu'une connexion est considéré comme en état de veille?".
Une connexion est considérée comme inactive lorsqu'il n'existe pas de données "transmis" donc, si l'un des
deux pairs sont bloqués sur un send(...) il y a effectivement des données transmises et la connexion n'est pas considérée comme inactive. Je suppose que la seule option que j'ai maintenant est de faire un ping/pong en utilisant envoie/recv avec délai, la déclaration d'une connexion "perdu" lors de ces minuteries expire.
OriginalL'auteur Gaetano Mendola
Gaetano, de l'OMI, TCP keep-alives peut être utilisé pour détecter les connexions mortes. Dans votre exemple, le client peut en fait être suspendu dans l'envoyer en attente pour le TCP tentatives d'échappement eux-mêmes. Selon le back-off de l'algorithme et de la pile TCP état de la machine, cela peut durer plusieurs minutes, sans keep-alive, et donc aucun moyen de gaz d'échappement keepcnt.
Je suppose que le serveur est principalement en lecture bloqué, dans ce cas, sa keep-alives sera envoyé à chaque keepidle/slowhz secondes (slowhz est souvent les 2 au lieu de 1), et il permet de détecter la perte de connexion assez rapidement.
Si vous capturez un paquet de trace à l'aide de tcpdump, vous verrez exactement ce qui se passe sur le fil.
OriginalL'auteur anon
Vous devez remplacer
SOL_TCP
avecIPPROTO_TCP
.Pour plus d'informations, suivez ces liens
OriginalL'auteur TMtech