Application client-serveur et événements
Application client-serveur et événements
Bonjour/bonsoir,
Client et utilisateur de PureBasic depuis de nombreuses années, je me trouve face à une situation bloquante en programmation client serveur. Et ce à cause de la gestion du réseau par événements dans purebasic.
Je vous présente mon objectif :
avoir une application serveur qui écoute uniquement sur le port 2018 (par exemple)
avoir une application client A qui transmet à intervalles réguliers des données d'une taille L sur le port 2018
avoir une application client B qui transmet à intervalles réguliers des données d'une taille ~L sur le port 2018
A reçoit ce que B envoie grâce à l'application serveur
B reçoit ce que A envoie grâce à l'application serveur
avoir une application cliente C qui reçoit la moyenne des valeurs envoyées par A et B grâce à l'application serveur. Si B n'envoie rien alors C recevra uniquement ce que A envoie. Si A n'envoie rien alors C recevra uniquement ce que B envoie.
Par exemple
A envoie 1020304050
B envoie 60708090A0
C recevra 3848586878 (ou calculera par lui même ces valeurs)
Tout mon problème réside dans la réalisation, coté serveur, de la moyenne. En effet lorsque je lis les événements réseaux, coté serveur, du client A je n'ai la possibilité que plus loin dans mon code de voir s'il y a des données envoyées au serveur par le client B. Du coup je suis bien embêté. La documentation informe qu'il faut appeler ReceiveNetworkData() uniquement après avoir reçu un événement #PB_NetworkEvent_Data. Cette manière de structurer le code par événement m’empêche de réaliser mon objectif.
Dois-je plutot tenter de faire en sorte que la moyenne soit calculée par l'application cliente C?
En y pensant je me dis que placer un header dans le paquet contenant un identifiant attribué par le serveur permettrait de savoir quel client envoie quoi. Mais lorsque A et B enverront des données comment C fera-t-il apres avoir reçu un paquet de A pour savoir qu'il y a un autre paquet en attente de la part de B? Je n'ai jamais eu de mal avec une application réseau mais dans ce cas, devoir structurer avec des evenements me pose de gros soucis. C'est pourquoi je fais appel à votre aide. Je n'attends pas particulièrement un code en réponse, mais plus une idée, une manière de faire....mais pourquoi pas du code si c'est plus simple de répondre ainsi pour vous. Je vous remercie et vous souhaite une bonne journée.
Client et utilisateur de PureBasic depuis de nombreuses années, je me trouve face à une situation bloquante en programmation client serveur. Et ce à cause de la gestion du réseau par événements dans purebasic.
Je vous présente mon objectif :
avoir une application serveur qui écoute uniquement sur le port 2018 (par exemple)
avoir une application client A qui transmet à intervalles réguliers des données d'une taille L sur le port 2018
avoir une application client B qui transmet à intervalles réguliers des données d'une taille ~L sur le port 2018
A reçoit ce que B envoie grâce à l'application serveur
B reçoit ce que A envoie grâce à l'application serveur
avoir une application cliente C qui reçoit la moyenne des valeurs envoyées par A et B grâce à l'application serveur. Si B n'envoie rien alors C recevra uniquement ce que A envoie. Si A n'envoie rien alors C recevra uniquement ce que B envoie.
Par exemple
A envoie 1020304050
B envoie 60708090A0
C recevra 3848586878 (ou calculera par lui même ces valeurs)
Tout mon problème réside dans la réalisation, coté serveur, de la moyenne. En effet lorsque je lis les événements réseaux, coté serveur, du client A je n'ai la possibilité que plus loin dans mon code de voir s'il y a des données envoyées au serveur par le client B. Du coup je suis bien embêté. La documentation informe qu'il faut appeler ReceiveNetworkData() uniquement après avoir reçu un événement #PB_NetworkEvent_Data. Cette manière de structurer le code par événement m’empêche de réaliser mon objectif.
Dois-je plutot tenter de faire en sorte que la moyenne soit calculée par l'application cliente C?
En y pensant je me dis que placer un header dans le paquet contenant un identifiant attribué par le serveur permettrait de savoir quel client envoie quoi. Mais lorsque A et B enverront des données comment C fera-t-il apres avoir reçu un paquet de A pour savoir qu'il y a un autre paquet en attente de la part de B? Je n'ai jamais eu de mal avec une application réseau mais dans ce cas, devoir structurer avec des evenements me pose de gros soucis. C'est pourquoi je fais appel à votre aide. Je n'attends pas particulièrement un code en réponse, mais plus une idée, une manière de faire....mais pourquoi pas du code si c'est plus simple de répondre ainsi pour vous. Je vous remercie et vous souhaite une bonne journée.
Re: Application client-serveur et événements
Je ne suis pas sûr de tout bien comprendre
Tout comme un évènement Windows retourne l'évènement ET l'ID la fenêtre concernée,
un évènement réseau retourne les données ET l'ID du client, même s'il y en a plusieurs.
Chaque paquet est identifié et tu peux savoir si un client est connecté ou pas.
Donc un moyen est de détecter si les clients A et B a se sont déconnectés avant de faire les moyennes
Voici un exemple de serveur et client, dérivé de ceux de la doc
(J'ai surtout remplacé les MessageRequester par des Debug pour voir tous les messages ensembles)
Lance le serveur puis le client, cela te donnera des indications sur les infos échangées.
Si ça peut t'aider (je débute en application réseau en PB)
Edit Corrigé suite à suggestion bobby.
Supression If SEvent et ajout Case #PB_NetworkEvent_None : Delay(10)
La charge CPU passe de 25 à 0.17% !
Tout comme un évènement Windows retourne l'évènement ET l'ID la fenêtre concernée,
un évènement réseau retourne les données ET l'ID du client, même s'il y en a plusieurs.
Chaque paquet est identifié et tu peux savoir si un client est connecté ou pas.
Donc un moyen est de détecter si les clients A et B a se sont déconnectés avant de faire les moyennes
Voici un exemple de serveur et client, dérivé de ceux de la doc
(J'ai surtout remplacé les MessageRequester par des Debug pour voir tous les messages ensembles)
Code : Tout sélectionner
Debug "SERVEUR"
InitNetwork()
Port = 6832
*Buffer = AllocateMemory(1000)
If CreateNetworkServer(0, Port)
Repeat
SEvent = NetworkServerEvent()
ClientID = EventClient()
Select SEvent
Case #PB_NetworkEvent_None
Delay(10)
Case #PB_NetworkEvent_Connect
Debug "A new client has connected !"
Case #PB_NetworkEvent_Data
ReceiveNetworkData(ClientID, *Buffer, 1000)
Debug "Client: " + ClientID + " a envoyé: " + PeekS(*Buffer, -1, #PB_UTF8)
Case #PB_NetworkEvent_Disconnect
Debug "Client: "+Str(ClientID)+" has closed the connection..."
; Quit = 1
EndSelect
Until Quit = 1
CloseNetworkServer(0)
Else
Debug "Can't create the server (port in use ?)."
EndIf
End
Code : Tout sélectionner
;Debug "CLIENT"
InitNetwork()
Port = 6832
ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
If ConnectionID
SendNetworkString(ConnectionID, "Données de A" + Chr(0), #PB_UTF8)
CloseNetworkConnection(ConnectionID)
EndIf
ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
If ConnectionID
SendNetworkString(ConnectionID, "Données de B" + Chr(0), #PB_UTF8)
CloseNetworkConnection(ConnectionID)
EndIf
Si ça peut t'aider (je débute en application réseau en PB)
Edit Corrigé suite à suggestion bobby.
Supression If SEvent et ajout Case #PB_NetworkEvent_None : Delay(10)
La charge CPU passe de 25 à 0.17% !
Dernière modification par Marc56 le jeu. 11/oct./2018 16:14, modifié 3 fois.
Re: Application client-serveur et événements
@Marc56 n'ayant pas de waitnetworkevent, je te conseille (coté serveur) de rajouter un case #PB_NetworkEvent_None : delay(xx)
Ca évitera d'avoir un serveur à 100% CPU pour rien.
@salutcava https://www.purebasic.fr/french/viewtop ... 77&start=3
Un exemple fonctionel de relation client serveur...
Ca évitera d'avoir un serveur à 100% CPU pour rien.
@salutcava https://www.purebasic.fr/french/viewtop ... 77&start=3
Un exemple fonctionel de relation client serveur...
Re: Application client-serveur et événements
Au niveau algo, je pense que tu dois donner un numéro à tes paquets, de façon à pouvoir faire les moyennes dans l'ordre par le serveur. Par exemple si les clients a et b envoient plusieurs nombres à la suite, la moyenne ne sera pas forcément bonne car le tcp/ip ne garantit pas l'ordre d'arrivée des paquets. Pour que cela fonctionne, il faut que tu ajoutes à tes nombres un numéro d'ordre. Par exemple, A envoie 1-123, B envoie 1-456, A envoie 2-765, B envoie 2-876 etc... La moyenne 1 sera (123+456)/2, la moyenne 2 sera (765+876)/2 etc.
Re: Application client-serveur et événements
Merci pour vos réponses marc, boby et djes.
Merci djes pour ton idée de donner un ordre aux paquets des deux clients émetteurs.
Je vais voir si je peux m'en sortir en suivant cette approche.
Merci!
Merci djes pour ton idée de donner un ordre aux paquets des deux clients émetteurs.
Je vais voir si je peux m'en sortir en suivant cette approche.
Merci!
Re: Application client-serveur et événements
(Supprimé. Réponse 1 modifiée avec les suggestions de Boby )
Dernière modification par Marc56 le jeu. 11/oct./2018 16:40, modifié 1 fois.
Re: Application client-serveur et événements
@Marc
C'est vraiment préférable de gérer le delay via l'event (ou plutot le non event) #PB_NetworkEvent_None que dans ta boucle principale, en cas de transfert de gros paquet, si tu delay est dans ta boucle, tu auras ton delay entre chaques ReceiveNetworkData(), alors que si tu met un delay uniquement si il n'y a pas d'activité réseau, bah tant qu'il y a du boulot pour le serveur, il va bosser, sans attendre 10 ms entre chaques écoute réseau. (J'suis d'accord que 10ms c'est vraiment quedal, mais sur un serveur qui se retrouve à gérer beaucoup de connexion, ça doit se sentire à un moment je pense...)
Code : Tout sélectionner
SEvent = NetworkServerEvent()
If SEvent
[...]
EndIf
Code : Tout sélectionner
Debug #PB_NetworkEvent_None
C'est vraiment préférable de gérer le delay via l'event (ou plutot le non event) #PB_NetworkEvent_None que dans ta boucle principale, en cas de transfert de gros paquet, si tu delay est dans ta boucle, tu auras ton delay entre chaques ReceiveNetworkData(), alors que si tu met un delay uniquement si il n'y a pas d'activité réseau, bah tant qu'il y a du boulot pour le serveur, il va bosser, sans attendre 10 ms entre chaques écoute réseau. (J'suis d'accord que 10ms c'est vraiment quedal, mais sur un serveur qui se retrouve à gérer beaucoup de connexion, ça doit se sentire à un moment je pense...)
Re: Application client-serveur et événements
Merci pour la réponse didactique, ça force à analyser plutôt que recopierSEvent = NetworkServerEvent()
If SEvent
Debug #PB_NetworkEvent_None
Pour une fois ce sont des lignes en trop qui bloquaient
Effectivement pour traiter #PB_NetworkEvent_None (= 0) il faut d'abord entrer dans la boucle Select, donc SEvent <> 0. Logique!
Ça fonctionne bien maintenant, tous mes programmes réseaux tournent à environ 0.17% de CPU contre 24% avant.
Re: Application client-serveur et événements
Pour ton problème de qui envoie quoi, il suffit d'imaginer une conversation à 4 par courrier : on met sur l'enveloppe le nom du destinataire, de l'expéditeur et la date. Pour transférer un courrier, tu le joins en entier. De cette manière, le destinataire peut tout déduire.
Pour ton problème de moyenne qui ne se fait que si a et b ont répondu, il faut forcément que cela soit rattaché à autre chose de commun, pour que les réponses soient coordonnées. Soit un numéro d'ordre, soit un numéro extérieur ou un signal commun. C'est difficile de dire mieux sans savoir à quoi ça se rapporte.
Pour ton problème de moyenne qui ne se fait que si a et b ont répondu, il faut forcément que cela soit rattaché à autre chose de commun, pour que les réponses soient coordonnées. Soit un numéro d'ordre, soit un numéro extérieur ou un signal commun. C'est difficile de dire mieux sans savoir à quoi ça se rapporte.
Re: Application client-serveur et événements
Voici plus d'informations sur le problème que je rencontre. Lors de mon tout premier poste j'ai essayé de simplifier au maximum mon vrai probleme.
Il se trouve que les données envoyées sont des données audio. Et donc la moyenne n'est pas une moyenne mais de quoi "mixer" les données audio.
Voilà tout.
Peut etre que le mix (la moyenne) devrait se faire coté serveur du coup?
Toujours est-il que j'ai ajouté en entete de mes données audio un identifiant unique aux émetteurs , comme suggéré dans une des réponses proposées.
Je vais voir comment je peux m'en sortir avec cette approche.
(je n'ai pas avancé plus ayant manqué de temps....(eh oui Black OPS 4 est sorti... )
Il se trouve que les données envoyées sont des données audio. Et donc la moyenne n'est pas une moyenne mais de quoi "mixer" les données audio.
Voilà tout.
Peut etre que le mix (la moyenne) devrait se faire coté serveur du coup?
Toujours est-il que j'ai ajouté en entete de mes données audio un identifiant unique aux émetteurs , comme suggéré dans une des réponses proposées.
Je vais voir comment je peux m'en sortir avec cette approche.
(je n'ai pas avancé plus ayant manqué de temps....(eh oui Black OPS 4 est sorti... )
Re: Application client-serveur et événements
Bonjour/Bonsoir,
Je reviens vers vous pour vous donner des nouvelles
De la manière que j'envisageais les choses...ca aurait été compliqué d'arriver à mes fins. Il aurait fallu identifier les émetteurs des packets audio et calculer leur durée et mixer le son etc etc
HEUREUSEMENT que le codec son que j'utilise gère le multistream...du coup tout va bien le problème est résolu. Les paquets arrivent les uns à la suite des autres et tout est géré automatiquement...Ahhhh les library...qu'est ce qu'on ne ferait pas sans elles....Cependant faire les choses par soit même à son petit coté stimulant qui ne me deplait pas
Les paquets arrivent donc les uns à la suite des autres et le multistream est géré sans soucis.
Merci à vous pour vos réponses, je vous aime. Bisous!
Vive Purebasic, je kiffe depuis des années!
Je reviens vers vous pour vous donner des nouvelles
De la manière que j'envisageais les choses...ca aurait été compliqué d'arriver à mes fins. Il aurait fallu identifier les émetteurs des packets audio et calculer leur durée et mixer le son etc etc
HEUREUSEMENT que le codec son que j'utilise gère le multistream...du coup tout va bien le problème est résolu. Les paquets arrivent les uns à la suite des autres et tout est géré automatiquement...Ahhhh les library...qu'est ce qu'on ne ferait pas sans elles....Cependant faire les choses par soit même à son petit coté stimulant qui ne me deplait pas
Les paquets arrivent donc les uns à la suite des autres et le multistream est géré sans soucis.
Merci à vous pour vos réponses, je vous aime. Bisous!
Vive Purebasic, je kiffe depuis des années!