Demande de conseil pour mise en place client/serveur tcp
Demande de conseil pour mise en place client/serveur tcp
Bonjour,
Je souhaiterais créer un binôme client/serveur en TCP. Sachant que je pourrais avoir simultanément 1200 clients connectés (au maximum) sur un LAN, quels sont les points auxquels je dois faire attention ? Par exemple, j'ai lu sur le forum que certains créent une thread par connexion.
La partie serveur afficherait la liste des client connectés et permettrait des envois de commandes aux clients sélectionnés.
La partie cliente ferait remonter au serveur des infos techniques et donc exécuterait aussi les commandes reçues du serveur.
Quelle est la meilleure approche ?
En vous remerciant par avance.
Je souhaiterais créer un binôme client/serveur en TCP. Sachant que je pourrais avoir simultanément 1200 clients connectés (au maximum) sur un LAN, quels sont les points auxquels je dois faire attention ? Par exemple, j'ai lu sur le forum que certains créent une thread par connexion.
La partie serveur afficherait la liste des client connectés et permettrait des envois de commandes aux clients sélectionnés.
La partie cliente ferait remonter au serveur des infos techniques et donc exécuterait aussi les commandes reçues du serveur.
Quelle est la meilleure approche ?
En vous remerciant par avance.
Re: Demande de conseil pour mise en place client/serveur tcp
Bonjour tatanas,
1200 clients et un serveur, ce n'est plus un binôme
Je ne pense pas que créer un thread par connexion soit une bonne idée (ni même faisable étant donné qu'il est possible que chaque thread se réserve un espace mémoire). (pas testé)
S'il s'agit comme pour l'un de tes projet de la gestions de périphériques par SNMP, je pense que le mieux est de faire du pooling SNMP dans le sens application vers les clients et d'utiliser les traps SNMP dans le sens client vers serveur (si les clients ont ce dispositif: les imprimantes réseau l'ont par exemple souvent)
1200 clients et un serveur, ce n'est plus un binôme
Je ne pense pas que créer un thread par connexion soit une bonne idée (ni même faisable étant donné qu'il est possible que chaque thread se réserve un espace mémoire). (pas testé)
S'il s'agit comme pour l'un de tes projet de la gestions de périphériques par SNMP, je pense que le mieux est de faire du pooling SNMP dans le sens application vers les clients et d'utiliser les traps SNMP dans le sens client vers serveur (si les clients ont ce dispositif: les imprimantes réseau l'ont par exemple souvent)
- Mindphazer
- Messages : 635
- Inscription : mer. 24/août/2005 10:42
Re: Demande de conseil pour mise en place client/serveur tcp
Tu peux aussi jeter un oeil ici : https://www.purebasic.fr/english/viewto ... 536083355b
(je ne sais absolument pas si ça peut répondre à ta demande !!)
(je ne sais absolument pas si ça peut répondre à ta demande !!)
Bureau : Win10 64bits
Maison : Macbook Pro M1 14" SSD 512 Go / Ram 16 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Maison : Macbook Pro M1 14" SSD 512 Go / Ram 16 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Re: Demande de conseil pour mise en place client/serveur tcp
Ce n'est pas un projet lié au snmp. Juste un moyen de récupérer des infos de postes clients sous Windows et leur transmettre des commandes à exécuter en local.
Donc clairement les requêtes partiraient des clients pour "alimenter" le serveur et parfois le serveur enverrait des ordres aux clients.
Lien intéressant pour des envois de données TCP supérieurs à 65536 octets ce qui semble être la limite des fonctions Purebasic.
Petite question liée à ce sujet : Comment doit on gérer la réception de données lorsque celles-ci sont incomplètes ? J'ai regardé quelques exemples de codes sur le forum mais les gens n'ont pas l'air de s'en soucier. Est-ce que ce genre de traitement convient ?
Donc clairement les requêtes partiraient des clients pour "alimenter" le serveur et parfois le serveur enverrait des ordres aux clients.
Lien intéressant pour des envois de données TCP supérieurs à 65536 octets ce qui semble être la limite des fonctions Purebasic.
Petite question liée à ce sujet : Comment doit on gérer la réception de données lorsque celles-ci sont incomplètes ? J'ai regardé quelques exemples de codes sur le forum mais les gens n'ont pas l'air de s'en soucier. Est-ce que ce genre de traitement convient ?
Code : Tout sélectionner
; réception de données envoyées par un SendNetworkString() en UTF8
DataReceived = ReceiveNetworkData(connectionID, *BufferReceive, BufferLen)
While DataReceived = BufferLen
resultat = resultat + PeekS(*BufferReceive, -1, #PB_UTF8)
DataReceived = ReceiveNetworkData(connectionID, *BufferReceive, BufferLen)
Wend
; traitement de resultat
Re: Demande de conseil pour mise en place client/serveur tcp
Tu ne veux pas utiliser les webservices (HTTPRequest()) ? cela serait bien plus simple et rapide à mettre en œuvre et à modifier. Tu peux écrire la partie serveur en PB ou utiliser un simple serveur web et un langage dynamique ou CGI.Juste un moyen de récupérer des infos de postes clients sous Windows et leur transmettre des commandes à exécuter en local.
Re: Demande de conseil pour mise en place client/serveur tcp
Disons que ça permettrait aux clients d'envoyer facilement les infos au serveur (web) mais le serveur ne pourrait envoyer ses ordres aux clients que si ces derniers hébergent aussi un serveur web, non ?
Re: Demande de conseil pour mise en place client/serveur tcp
Le principe du webservice c'est une question/réponse.tatanas a écrit :Disons que ça permettrait aux clients d'envoyer facilement les infos au serveur (web) mais le serveur ne pourrait envoyer ses ordres aux clients que si ces derniers hébergent aussi un serveur web, non ?
Le client envoie la question par GET ou POST (dans l'URL ou dans le corps)
Le serveur répond par une page unique formatée (texte, html, json, xml)
À partir de là, il suffit que le client analyse le contenu de la réponse et exécute l'ordre reçu.
La seule différence par rapport au web normal c'est qu'on n'utilise pas de navigateur. C'est au client (programme) de voir ce qu'il veut faire avec le fichier reçu. Donc ici, par exemple tu utilises un FindString() pour lire une commande dans le texte que tu utilises ensuite dans RunProgram()
Re: Demande de conseil pour mise en place client/serveur tcp
Je comprends bien. Mais le client ne sait pas à priori quand il va recevoir un ordre. Or dans le cas que tu expliques, il devrait envoyer une requête au serveur pour savoir si le serveur veut lui donner un ordre. Du coup il faudrait sonder très régulièrement le serveur pour être réactif à un ordre qui pourrait être donné une fois par mois comme plusieurs fois par jour. Est-ce un fonctionnement très propre ?
Re: Demande de conseil pour mise en place client/serveur tcp
Je partais de l'hypothèse que c'était le client qui initialisait une connexion et devait faire quelque-chose en fonction de la réponse serveur (exemple: Windows update où le client va voir ce qui est dispo, puis charge et installe seul)
Si le serveur qui doit aussi pouvoir atteindre le client à tout moment alors il faut que le client se comporte effectivement comme un serveur.
Si le serveur qui doit aussi pouvoir atteindre le client à tout moment alors il faut que le client se comporte effectivement comme un serveur.
Re: Demande de conseil pour mise en place client/serveur tcp
Donc, je reste sur mon client/serveur TCP.
Concernant ma question au sujet de ReceiveNetworkData(). Quelle est la bonne méthode pour être certain que toutes les données sont bien arrivées ?
J'ai du mal à me rendre compte comment PureBasic gère cela en interne. Il est bien indiqué dans la doc de ReceiveNetworkData() : "If 'Result' is equal to DataBufferLength then more data is available to be read". Mais puisque ReceiveNetworkData() n'est censé être appelé qu'après la réception de #PB_NetworkEvent_Data, ma boucle while n'a peut être aucun intérêt ?
Concernant ma question au sujet de ReceiveNetworkData(). Quelle est la bonne méthode pour être certain que toutes les données sont bien arrivées ?
J'ai du mal à me rendre compte comment PureBasic gère cela en interne. Il est bien indiqué dans la doc de ReceiveNetworkData() : "If 'Result' is equal to DataBufferLength then more data is available to be read". Mais puisque ReceiveNetworkData() n'est censé être appelé qu'après la réception de #PB_NetworkEvent_Data, ma boucle while n'a peut être aucun intérêt ?
Re: Demande de conseil pour mise en place client/serveur tcp
Tu peux mettre un buffer plus grand que la taille maxi du message à recevoir et couper le message à la longueur des octets réellement reçus (retournée par ReceiveNetworkData()) donc pas besoin de boucle.
Exemple (basé sur les deux exemples de la doc)
Lancer le serveur, puis le client
ServeurAvec PeekS(*Buffer, -1, #PB_UTF8) tu recois la totalité du buffer.
Avec un buffer plus petit que le plus grand message, je pense que tu devrais effectivement boucler et probablement tester un caractère de fin qui serait à ajouter (EOT ? ETX ?)
Client
J'ai peut -être encore répondu à coté, mais ça m'a permis de comprendre des trucs nouveaux
Je n'ai jamais fais d'application client/serveur purement en PB, mais ceci fonctionne.
Tiens, je vais créer mon propre ICQ en PB
Exemple (basé sur les deux exemples de la doc)
Lancer le serveur, puis le client
Serveur
Code : Tout sélectionner
If InitNetwork() = 0
MessageRequester("Error", "Can't initialize the network !", 0)
End
EndIf
Port = 6832
*Buffer = AllocateMemory(1000)
If CreateNetworkServer(0, Port)
Debug "Server created (Port " + Str(Port)+")."
Repeat
SEvent = NetworkServerEvent()
If SEvent
ClientID = EventClient()
Select SEvent
Case #PB_NetworkEvent_Connect
Debug "Server - A new client has connected ! " + Str(ClientID)
Case #PB_NetworkEvent_Data
Nb_Octets = ReceiveNetworkData(ClientID, *Buffer, 1000)
;Debug "Reçu: ("+ Nb_Octets +") >>>" + PeekS(*Buffer, -1, #PB_UTF8) + "<<<"
Debug "Reçu: ("+ Nb_Octets +") >>>" + PeekS(*Buffer, Nb_Octets, #PB_UTF8) + "<<<"
Case #PB_NetworkEvent_Disconnect
Debug "Client "+Str(ClientID)+" has closed the connection..."
Quit = 1
EndSelect
EndIf
Until Quit = 1
Debug "PureBasic - Server: END"
CloseNetworkServer(0)
Else
MessageRequester("Error", "Can't create the server (port in use ?).", 0)
EndIf
End
Avec un buffer plus petit que le plus grand message, je pense que tu devrais effectivement boucler et probablement tester un caractère de fin qui serait à ajouter (EOT ? ETX ?)
Client
Code : Tout sélectionner
If InitNetwork() = 0
MessageRequester("Error", "Can't initialize the network !", 0)
End
EndIf
NewList Jour$()
AddElement(Jour$()) : Jour$() = "Lundi"
AddElement(Jour$()) : Jour$() = "Mardi"
AddElement(Jour$()) : Jour$() = "Mercredi"
AddElement(Jour$()) : Jour$() = "Jeudi"
AddElement(Jour$()) : Jour$() = "Vendredi"
AddElement(Jour$()) : Jour$() = "Samedi"
AddElement(Jour$()) : Jour$() = "Dimanche"
Port = 6832
ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
If ConnectionID
ForEach Jour$()
SendNetworkString(ConnectionID, Jour$(), #PB_UTF8)
Delay(1000)
Next
CloseNetworkConnection(ConnectionID)
Else
MessageRequester("PureBasic - Client", "Can't find the server (Is it launched ?).", 0)
EndIf
End
Je n'ai jamais fais d'application client/serveur purement en PB, mais ceci fonctionne.
Tiens, je vais créer mon propre ICQ en PB
Dernière modification par Marc56 le mar. 12/mai/2020 14:55, modifié 1 fois.
Re: Demande de conseil pour mise en place client/serveur tcp
En effet ça fonctionne ainsi et la logique se tient
En fouinant j'ai aussi trouvé ce lien : http://forums.purebasic.com/english/vie ... 7e1ff8c70b
Il s'avère qu'il y a un soucis lorsque le nombre de bytes retournés par ReceiveNetworkData() est la même que la taille du buffer ET que le paquet envoyé fait aussi cette taille.
Du coup on ne peut pas déterminer si la réception est bien terminée ou s'il en reste, mais si on relance un ReceiveNetworkData(), alors on reste bloqué sur cette fonction qui attends que d'autres données arrivent alors qu'il n'y a plus rien à recevoir.
Et en page 2 une solution qui permet de connaitre le nombre de bytes en attente dans le socket, ce qui permet d'allouer un buffer de la bonne taille directement.
En fouinant j'ai aussi trouvé ce lien : http://forums.purebasic.com/english/vie ... 7e1ff8c70b
Il s'avère qu'il y a un soucis lorsque le nombre de bytes retournés par ReceiveNetworkData() est la même que la taille du buffer ET que le paquet envoyé fait aussi cette taille.
Du coup on ne peut pas déterminer si la réception est bien terminée ou s'il en reste, mais si on relance un ReceiveNetworkData(), alors on reste bloqué sur cette fonction qui attends que d'autres données arrivent alors qu'il n'y a plus rien à recevoir.
Et en page 2 une solution qui permet de connaitre le nombre de bytes en attente dans le socket, ce qui permet d'allouer un buffer de la bonne taille directement.
Re: Demande de conseil pour mise en place client/serveur tcp
Perso j'aime pas trop mettre des API directes, je préfère utiliser les pièces d'origine certifiés par Fred
Cela dit, comme c'est toi qui fera l'application client et celle du serveur, tu peux fixer d'autorité la taille des chaines envoyées et celle du buffer.
Au besoin, tu mets un caractère de fin (ex: Chr(4) = EOT (End Of Transmission) ou ETX etc, c'est fait pour ne pas être confondu avec le reste et tu le teste à l'arrivée comme dernier caractère du tampon (Right())
Quelque-chose comme ça
(pas testé)
Cela dit, comme c'est toi qui fera l'application client et celle du serveur, tu peux fixer d'autorité la taille des chaines envoyées et celle du buffer.
Au besoin, tu mets un caractère de fin (ex: Chr(4) = EOT (End Of Transmission) ou ETX etc, c'est fait pour ne pas être confondu avec le reste et tu le teste à l'arrivée comme dernier caractère du tampon (Right())
Quelque-chose comme ça
Code : Tout sélectionner
Tmp_Buf = PeekS(*Buffer, Nb_Octets -1, #PB_UTF8)
If Right(Tmp_Buf , 1) = Chr(4) : Break : EndIf
Re: Demande de conseil pour mise en place client/serveur tcp
Oui je vais peut être faire ça.
Et vu que l'un des clients de ce serveur sera un module d'administration, je pense qu'il requêtera le serveur en webservices puisqu'il ne fera que récupérer des données.
Un pti mix des 2 solutions finalement.
Et vu que l'un des clients de ce serveur sera un module d'administration, je pense qu'il requêtera le serveur en webservices puisqu'il ne fera que récupérer des données.
Un pti mix des 2 solutions finalement.