web-dev-qa-db-fra.com

Vérifiez si la prise est connectée ou non

J'ai une application qui doit envoyer des données à un serveur à un moment donné. Le moyen le plus simple serait de fermer la connexion, puis de l'ouvrir à nouveau lorsque je souhaite envoyer quelque chose. Mais je veux garder la connexion ouverte, donc quand je veux envoyer des données, je vérifie d'abord la connexion en utilisant cette fonction:

bool is_connected(int sock)
{
    unsigned char buf;
    int err = recv(sock,&buf,1,MSG_PEEK);
    return err == -1 ? false : true;
}

La mauvaise partie est que cela ne fonctionne pas. Il se bloque lorsqu'il n'y a pas de données à recevoir. Que puis-je faire? Comment puis-je vérifier si la connexion est toujours ouverte?

17
opc0de

Ne vérifiez pas d'abord, puis envoyez. C'est un effort gaspillé et ne fonctionnera pas de toute façon - le statut peut changer entre le moment où vous vérifiez et le moment où vous envoyez. Faites simplement ce que vous voulez faire et gérez l'erreur en cas d'échec.

Pour vérifier l'état, utilisez:

int error_code;
int error_code_size = sizeof(error_code);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
24
David Schwartz

Vous devez activer le comportement non bloquant, en définissant O_NONBLOCK en utilisant fcntl. Une manière simple mais non standard d'effectuer une lecture non bloquante serait d'utiliser:

recv(sock, &buf, 1, MSG_PEEK | MSG_DONTWAIT);

Ensuite, vous devez vérifier errno s'il échoue. Il peut échouer avec EAGAIN ou il peut échouer avec EBADF ou ENOTCONN etc.


De toute évidence, la façon la plus simple et la plus propre de gérer cela serait d'éviter "d'oublier" si la prise est connectée ou non. Vous remarquerez si le socket est déconnecté une fois qu'un recv renvoie 0 ou un send renvoie EPIPE.

12
cnicutar

L'utilisation par défaut de TCP ne permet pas une détection très rapide des sockets morts (en dehors de la fermeture normale), donc je suggère qu'une fonction "is_connected" comme celle-ci est largement inutile à toutes fins pratiques. Envisagez d'implémenter une couche persistante de la couche application et suivez si elle est active en fonction des réponses opportunes (ou de leur absence).

edit: après avoir posté, je vois le lien de BoBTFish, qui est en fait la même chose.

3
mark