Voir le sujet précédent :: Voir le sujet suivant |
Auteur |
Message |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Lun Nov 18, 2002 4:37 pm Sujet du message: pb socket |
|
|
Bonjour
je suis en train de développer un client/serveur. Au niveau serveur lorsqu'on attend une socket client on utilise la fonction accept:
socket_client = accept(socket_serveur_descr,(struct sockaddr *)&client,&taille_client);
Le pb c'est que cette fonction est bloquante et tant qu'il n'y a pas de socket client à se connecter la fonction attend. Comment y remédier?
Touti |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
|
Revenir en haut |
|
 |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Mar Nov 19, 2002 11:07 am Sujet du message: |
|
|
question supplémentaire. J'ai vu qu'avec le select on pouvait savoir si une demande de connexion de socket était en attente. Maintenant dans le cas que j'ai une connexion entre mon serveur et mon client, est ce que je peux savoir si mon client m'a envoyé un message (si je l'ai reçu plutot) en utilisant la commande select ou bien faut il que je passe forcément par la commande recv.
Touti |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
Posté le: Mar Nov 19, 2002 12:24 pm Sujet du message: |
|
|
le mieux est de gérer la connexion dans un thread independant pour
eviter tout probleme de blocage _________________ Creer son site - Hebergement - Jumeaux |
|
Revenir en haut |
|
 |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Mar Nov 19, 2002 2:15 pm Sujet du message: |
|
|
désolé pas compris la réponse.
Pour être plus précis, la fonction select sert uniquement à savoir si une demande de connexion est adressé au serveur ou bien a t'elle d'autres fonctionnalités que je ne connais pas? Par exemple m'avertir si un message est arrivé (équivalent du recv). |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
Posté le: Mar Nov 19, 2002 8:42 pm Sujet du message: |
|
|
select()--Multiplexage Synchrone d'E/S
Cette fonction a quelque chose d'étrange, mais elle est TRES UTILE. Prenez la situation suivante: vous êtes un serveur et vous voulez attendre une connexion entrante mais aussi garder la connection que vous avez déjà.
Pas de problème vous vous dites, un simple accept() et deux appels à recv(). Pas si vite! Que se passera t-il s-il y a un blocage sur un accept()? Comment allez vous recevoir des données avec recv() en même temps? Utilisez des sockets non_bloquante!Pas question! Vous ne voulez pas être un consommateur record de CPU? Quoi alors ?
select() vous offre le possibilité de surveiller plusieurs sockets en même temps. Cela va vous permettre de savoir laquelle est prête à la lecture ou à l'écriture et si une exception se produit sur une socket si vous voulez réellement le savoir.
Sans plus de palabres, voici le prototype de select():
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int numfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
La fonction surveille des ensembles de descripteurs de fichiers et plus particulierement readfds, writefds, et exceptfds. (On parlera d'ensemble pour parler d'ensemble de descripteur de fichier) Si vous voulez voir si vous pouvez lire à partir de l'entrée standard et sur quelques sockets , ajoutez les descripteurs de fichiers 0 et sockfd à l'ensemble readfds. Le paramètre numfds doit être mis à la valeur du fichier le plus haut plus un. Dans cet exemple, il doit être mis a sockfd+1, assurant ainsi qu'il est supérieur a l'entrée standard (0).
Quand select() se termine, readfds sera modifié avec la fonction réflexe disant que le descripteur de fichier que vous avez sélectionné est près a la lecture. Vous pouvez les tester avec les macros FD_ISSET(), suivantes.
Avant d'aller plus avan , je vais vous expliquer comment manipuler ces ensembles. Chaque ensemble est de type fd_set. Les macros suivantes agissent sur ce type:
FD_ZERO(fd_set *set) - initialise l'ensemble
FD_SET(int fd, fd_set *set) - Ajoute fd à l'ensemble
FD_CLR(int fd, fd_set *set) - Elimine fd de l'ensemble
FD_ISSET(int fd, fd_set *set) - test pour savoir si fd fait parti de l'ensemble
Finalement, qu'est ce que c'est que cette struct timeval sortie de la jungle? Bien, il y a des moment ou vous ne voulez pas attendre une éternité que quelqu'un vous envoi des données. Peut être que toutes les 96 secondes vous voulez afficher "En cours..." sur le terminal même si rien ne se passe. Cette structure dédiée au temps vous autorise à spécifier un TIMEOUT. Si cette période s'achève et que select() n'a pas trouvé de descripteurs prêt, alors la fonction prendra la main et le programme continuera.
La struct timeval contient les champs suivants:
struct timeval {
int tv_sec; /* secondes */
int tv_usec; /* microsecondes */
};
Affectez à tv_sec le nombre de secondes à attendre, et à tv_usec le nombre de micro-secondes. Oui, ce sont des microsecondes, et non des millisecondes. Il y a 1000 micro-seconds dans une millisecondes et 1 000 000 micro-secondes dans une secondes. Pour alors cela s'appelle t-il "usec" ? Le "u" est en fait la lettre grec Mu utilisée ici pour dire micro. Alors, au retour de la fonction, timeout peut être mit à jour pour indiquer combien de temps il reste. Cela dépends de la couleur de l'Unix que vous utilisez.
Yeah! Nous avons un chronomètre précis à la micro-seconde! Mais ne comptez pas trop dessus. Les Unix standards ont une résolution temporelle de 100 milliseconds, alors vous aurez probablement à attendre au moins ce temps, même si vous réglez votre struct timevalà une valeur plus petite.
Autre point intéressant: Si vous positionnez les champs de votre structure struct timeval à 0, select() fera un timeout immédiatement, et interrogera tous les descripteurs de fichier dans vos ensembles. Si vous mettez le paramètre timeout a NULL, il ne fera jamais de timeout, et attendra que le premier descripteur soit prêt. Finalement, si vous n'êtes pas intéressé par une attente quelconque, vous pouvez passez à select() , NULL comme paramètre.
L'exemple suivant attends 2.5 secondes que quelques choses arrive sur l'entrée standard:
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#define STDIN 0 /* Descripteur de fichier pour entrée standard */
main()
{
struct timeval tv;
fd_set readfds;
tv.tv_sec = 2;
tv.tv_usec = 500000;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
/* ignorer writefds et exceptfds: */
select(STDIN+1, &readfds, NULL, NULL, &tv);
if (FD_ISSET(STDIN, &readfds))
printf("Une touche à été pressée!\n");
else
printf("Timed out.\n");
}
Si vous lancez ce programme à partir d'un terminal (qui bufferise la ligne), vous devrez appuyer sur la touche RETURN ou il y aura un time out.
Maintenant, plusieurs d'entre vous peuvent pensez que c'est là la bonne méthode pour attendre les données sur une socket datagram -- et vous avez raison cela peut l'être. Certain unix implémentent select pour cette utilisation, et d'autres non. Vous devriez regarder les pages de manuel de votre système pour savoir de quelles manière vous allez aborder le problème.
Pour conclure sur l'appel système select(): si vous avez une socket qui est en train d'écouter avec listen(), vous pouvez regarder si il y a une nouvelle connection en mettant le descripteur de socket dans l'ensemble readfds . _________________ Creer son site - Hebergement - Jumeaux |
|
Revenir en haut |
|
 |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Mer Nov 20, 2002 5:23 pm Sujet du message: |
|
|
ok merci.
autre question, comment faire en sorte que la fonction recv ne soit pas bloquante si mon client ne m'envoie rien? |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
|
Revenir en haut |
|
 |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Mer Nov 20, 2002 5:44 pm Sujet du message: |
|
|
et où je le positionne? |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
|
Revenir en haut |
|
 |
touti jeune mioche

Inscrit le: 16 Oct 2002 Messages: 46
|
Posté le: Mer Nov 20, 2002 6:06 pm Sujet du message: |
|
|
j'ai une erreur à la compil, il ne connait pas le flag MSG_DONTWAIT.
que faire?
je rappelle que je suis sous visual C++ et que je code en C. |
|
Revenir en haut |
|
 |
Salemioche salemioche


Inscrit le: 05 Avr 2002 Messages: 350 Localisation: FR- BIOT
|
Posté le: Mer Nov 20, 2002 6:22 pm Sujet du message: |
|
|
oups, mea culpa. desole, les winsocks sont un grand mystere pour moi  _________________ Creer son site - Hebergement - Jumeaux |
|
Revenir en haut |
|
 |
ttbidouille jeune mioche

Inscrit le: 21 Juin 2002 Messages: 10
|
Posté le: Mer Déc 04, 2002 6:39 pm Sujet du message: |
|
|
Socket sous VC (Sans MFC)
tu doit utiliser le WSAAsyncSelect(..) pour ne pas blocker sous Visual C++
cette fonction pour asynchrone le Socket ....
MFC:
Class CSocket et CAsyncSocket ..
voir MSDN ....
ttbidouille _________________ ttbidouille@yahoo.com |
|
Revenir en haut |
|
 |
|