Salut,
J'ai décidé de faire tout mon moteur client/serveur en C et jusqu'à maintenant tout allait bien. A présent je suis un peu embêté.
Toutes les 5s je dois envoyer un packet par UDP sur mon serveur.
Celui-ci me renvoie (en UDP toujours) une réponse au client.
Le problème c'est que si la connexion est pourrie (aka 3G), ben l'attente de la réception plante tout mon programme
Du coup j'ai googlé un peu mais je suis un peu pommé entre les gens qui parlent "d'asynchrone, de socket non bloquante, de consomation abusive de CPU en utilisant ceci ou cela..." bref je suis perdu
Quelqu'un pourrait m'éclairer la dessus ?
Mon code : http://pastebin.com/zVJ6RkNM
Bonjour,
Je vais aider à ma manière...
« Toutes les 5s je dois envoyer un packet par UDP sur mon serveur. »
Il est sûrement là ton problème. Pourquoi tu fais ça ? À quoi ça te sert ?
On dit "bound" pas "binded" ![]()
(-> printf("binded \n");)
Sinon si tu connais pas les sockets non bloquantes :
http://www.beej.us/guide/bgnet/output/html/multipage/advanced.html#blocking
« Toutes les 5s je dois envoyer un packet par UDP sur mon serveur. »
Il est sûrement là ton problème. Pourquoi tu fais ça ? À quoi ça te sert ?
Je suis toujours sur mon application de streaming, c'est un protocole (RTCP) qui permet de faire de la QoS
Ça ne répond pas vraiment à ma question.
Pourquoi 5s ? pourquoi de l'UDP ? quel(s) problème(s) cela résout ?
Pour répondre à tes questions une par une :
Pourquoi 5s :
En gros le protocole RTCP permet d'envoyer au serveur des informations sur ton streaming (nombre de packets envoyés, timestamp ntp au moment de l'envoi, synchronisation audiovisuelle) et le serveur renvoie ce qu'il a effectivement reçu, essaye de gérer son buffer comme il le peut pour avoir la synchro et une vidéo fluide.
J'ai lu pas mal de doc (RFC, livre, stackoverflow), lu du code (ffmpeg, pris contact avec des professionnels du milieu) qui sont à peu près d'accord pour dire qu'on doit envoyer un packet toutes les 2 à 10s. Vu que les session sur iPhone sont courtes mais qu'en même temps j'ai pas trop de bande passante j'ai coupé la poire en deux
Pourquoi l'UDP :
Pour l'UDP c'est pas vraiment un choix personnel, normalement ça doit être du TCP car les informations envoyés sont cruciales, mais il se trouve que le serveur que j'utilise (Wowza Media Serveur) m'impose l'UDP (je crois)
Quels problèmes cela résout ?
J'ai plus ou moins répondu à cette question au début, c'est surtout pour maintenir un stream fluide et garder une bonne synchro entre le son et la vidéo
ah oui et du côté serveur, il me renvoi le temps ntp au moment de la réception, le nombre de packets perdu et quelques autres info me permettant de savoir par exemple que le réseau est pourri et qu'il faut d'urgence baisser la qualité de la vidéo
Pourquoi pas utiliser select() pour checker si tu peux lire sur le socket ou pas ? Je sais pas si c'est ok avec l'UDP mais ça devrait passer. Tu peux boucler dessus avec un petit sleep et ça consomme rien
Je vais tester, ca consommerai moins qu'avec la fonction fcntl() ?
utilise select (avec un timeout) pour éviter les 100% cpu
et une boucle infini dans un serveur c'est normal ![]()
tu manages tes sockets avec quoi actuellement ?
Je te conseille select() simple d'utilisation.
(je suis vraiment débutant a 100% en programmation réseau bas niveau, j'ai toujours fait ça dans des langages de haut niveau)
Utilise select (avec un timeout) pour éviter les 100% cpu
Si j'ai bien compris c'est bloquant select() non ? En gros il faut que je fasse un while(1){select();sleep(0.01);} dans un autre thread ?
tu manages tes sockets avec quoi actuellement ?
J'ai pas compris la question
Tu as lu le man de select() ?
En gros ça te permet de savoir si il y a des choses a lire sur tes sockets ou non,
savoir si tu peux écrire dessus ou non.
Tu peux le mettre bloquant (le programme ne bouge plus tant que tes sockets ne change pas d’état)
ou lui mettre un timeout (il attend un temps puis passe a la suite du programme), c'est le dernier paramètre (struct timeval)
et il faudra que tu utilise FD_ZERO et FD_SET pour tes fd_set (les paramètres de select()), enfin si tu t'en sort pas je posterais un exemple
Oui j'ai lu le man de select() plusieurs fois et ça me laisse un peu perplexe justement ^^' L'idée c'est que je pensais qu'il existait un truc tout fait pour faire des sockets asynchrones en C alors qu'en fait pas du tout ![]()
En effet j'avais fini par comprendre ça... Vu que mon traitement ne doit surtout pas s'arrêter il faut donc threader la bête...
je suis un peu fatigué je up le topic demain matin quand j'aurais refait des tests avec un petit while(1)
pas besoin de thread
en gros tu as ta main loop
while(truc)
{
my_set(..); // la tu va faire tes fd_zero/fd_set et le select
my_read(..); // la tu utilise FD_ISSET sur tous tes sockets
// et la tu fais la suite de ton traitement
}
et tu met un petit timeout a ton select pour eviter le 100% cpu
je suis pas sur que cela soit une bonne idée le timeout car j'ai une contrainte temporelle assez forte au niveau du traitement (encodage de vidéo)
Tu n'est pas obligé d'en mettre mais si tu veux pas que ton programme prenne 100% du CPU il va bien falloir pauser à un endroit.
Et ça a pas besoin d'être long le timeout, ça peut être 20 microsecondes.
En passant tu peux ne pas mettre de timeout au select mais il faudra bien pauser à un moment.
Oki, j'ai fais marcher la bête comme ça, corrigez moi si ça semble foireux ![]()
http://pastebin.com/7eucRNp6