PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 2024 → Problème Ouverture Websocket
Problème Ouverture Websocket
Débuté par Freddykong, 19 juin 2017 18:02 - 8 réponses
Membre enregistré
60 messages
Popularité : +4 (4 votes)
Posté le 19 juin 2017 - 18:02
bonjour, j'essaie de faire tourner le code décrit sur la page concernant les websocket:
https://doc.pcsoft.fr/?1000017192
Le problème est que lorsque je lance une connexion depuis le client ,le server reçoit bien la connexion mais mon client m'informe instantanément de la fermeture de la socket .... J'ai essayé avec une version simplifié du server, qui crée un thread affichant un message "Info("...")" lors d'une connexion, en bloquent avec une temporistation le thread, mais rien à faire...
Membre enregistré
12 messages
Popularité : +7 (7 votes)
Posté le 26 septembre 2019 - 16:54
Bonjour,
moi je ressui de faire la connexion , mais je suis bloque au l'envoi d'une message de serveur a client
Membre enregistré
1 304 messages
Popularité : +47 (51 votes)
Posté le 27 septembre 2019 - 18:43
Salut,

Il existe un exemple didactique : WD Utilisation des sockets

Bon Dev
Daryl

--
http://www.concept4u2.com
Membre enregistré
12 messages
Popularité : +7 (7 votes)
Posté le 29 septembre 2019 - 13:39
Bonjour,
c'est bon je trouve la solution merci a tout
Membre enregistré
12 messages
Popularité : +7 (7 votes)
Posté le 30 septembre 2019 - 16:01
Voila mon code qui fonctionne correctement :Application Windev
PROCEDURE CréeSocketServeur
Procedure CréeSocketServeur()

IF PAS SocketExiste(sSocketServeur) THEN
IF PAS SocketCrée(sSocketServeur,gnPort,gsIP_Serveur) THEN
Erreur(ErreurInfo(errComplet))
RETOUR
END
TableauSupprimeTout(gtabCanals)
TraceTest("socket crée : "+sSocketServeur)
IF ThreadEtat("th_AttenteConnexionClient") <> threadEnCours THEN
ThreadExecute("th_AttenteConnexionClient",threadNormal,AttenteConnexionClient)
END
END


AttenteConnexionClient
Procedure AttenteConnexionClient()

TANTQUE SocketExiste(sSocketServeur)
sCanal est une chaîne

IF SocketAttendConnexion(sSocketServeur) THEN
sCanal = SocketAccepte(sSocketServeur)
gsCanal = sCanal
Ajoute(gtabCanals,gsCanal)
IHM_aff_ClientsConnecte()
TraceTest("sCanal : "+sCanal)
//sMsgRecuParClient est une chaîne = SocketLit(sCanal)
//TraceTest("MSG sCanal : "+sMsgRecuParClient)
ThreadExecute(sCanal,threadNormal,TraitmentCanal,sCanal)
END

FIN


serveurSocketCréeMsg

Procedure serveurSocketCréeMsg(sMsgServeurVersClient)

IF sMsgServeurVersClient = "" THEN
RETOUR
END

tabClientDeconnecte est un tableau de chaînes
POUR TOUT sCanalSocket de gtabCanals

//if SocketExiste(sSocketServeur) THEN
//IF SocketExiste(gsCanal) THEN
IF SocketExiste(sCanalSocket) THEN
//SectionCritiqueDébut("socket_serveur")
IF PAS SocketEcrit(sCanalSocket,sMsgServeurVersClient) THEN
//if pas SocketEcrit(gsCanal,sMsgServeurVersClient) THEN
//EurreurSockettxt(ErreurInfo(errComplet))
//SectionCritiqueFin("socket_serveur")
//RETOUR
TraceTest("message n'est pas envoie au Canal : "+sCanalSocket)
n est un entier = TableauCherche(gtabCanals,tcLinéaire,sCanalSocket)
IF n >0 THEN
TraceTest("suppression de canal : "+gtabCanals[n])
//TableauSupprime(gtabCanals,n)
Ajoute(tabClientDeconnecte,sCanalSocket)
IHM_aff_ClientsConnecte()
END
ThreadArrête(sCanalSocket)
SocketFerme(sCanalSocket)
END

IF sMsgServeurVersClient <>"" THEN
IF PAS fFichierExiste(sFichierTextMsgEnvoie) THEN
fCrée(sFichierTextMsgEnvoie)
END

sText est une chaîne = fChargeTexte(sFichierTextMsgEnvoie)
sText += DateVersChaîne(DateSys())+" "+HeureVersChaîne(HeureSys())+ " : "+ sMsgServeurVersClient+RC
fSauveTexte(sFichierTextMsgEnvoie,sText)
END
// SectionCritiqueFin("socket_serveur")
ELSE
//CréeSocketServeur()
//SectionCritiqueFin("socket_serveur")
//Socket n'existe pas
TraceTest("Socket n'existe pas , Canal : "+sCanalSocket)
n est un entier = TableauCherche(gtabCanals,tcLinéaire,sCanalSocket)
IF n >0 THEN
//TableauSupprime(gtabCanals,n)
Ajoute(tabClientDeconnecte,sCanalSocket)
END
ThreadArrête(sCanalSocket)
SocketFerme(sCanalSocket)
IHM_aff_ClientsConnecte()
END

FIN

//Suppression de Client Deconnecte
POUR TOUT sCanalClient de tabClientDeconnecte
n est un entier = TableauCherche(gtabCanals,tcLinéaire,sCanalClient)
IF n >0 THEN
TableauSupprime(gtabCanals,n)
IHM_aff_ClientsConnecte()
END
FIN
Membre enregistré
12 messages
Popularité : +7 (7 votes)
Posté le 30 septembre 2019 - 16:15
Pour Crée un WebSocket c'est un peut différente que le socket normal.
webSocket Cree par WINDEV pour l'application serveur, et un site web cree par WEBDEV pour l'application Client :

wsServeurCréeSocket
Procedure wsServeurCréeSocket()
// Code de la procédure locale : Ecoute des messages envoyés par le client socket.

IF SocketExiste(sSocketServeur) THEN
Info("Socket Existe Deja")
RETOUR
END


// Création du serveur de sockets pour effectuer l'écoute des messages arrivants
SI SocketCrée(sSocketServeur, gnPort) = Faux ALORS
Erreur("Erreur de création " + ErreurInfo(errMessage))
SINON
// Process (ou thread) d'écoute des messages
// Ce traitement est exécuté en tâche de fond
// On écoute en permanence car on ne sait pas quand un message arrive
TableauSupprimeTout(gtabCanals)
ThreadExecute("Th_ProcédureAttenteClient", threadNormal, ProcédureAttenteClient)
TraceTest("webSocket Serveur crée")
FIN
//-----------------------------------------------------------


Procedure ProcédureAttenteClient()
//-----------------------------------------------------------
// Procédure appelée dans le thread d'écoute

// Boucle sans fin afin d'attendre une connexion d'un client.
// Dès qu'un client se connecte pour envoyer un message,
// un thread est lancé afin de gérer les messages arrivants.
// La procédure ProcédureGestion gère les messages arrivants.
BOUCLE
Multitâche(0)
SI SocketAttendConnexion(sSocketServeur) ALORS
Canal est une chaîne
Canal = SocketAccepte(sSocketServeur)
Ajoute(gtabCanals,Canal)
SocketChangeModeTransmission(Canal, SocketSansMarqueurFin)
ThreadExecute(Canal, threadNormal, ProcédureGestioncanal, Canal)
FIN
FIN

//--------------------------------------------------------------


Procedure ProcédureGestioncanal(Canal)

sRequête est une chaîne ANSI
tabProtocol est un tableau de chaînes
sRes est une chaîne
sProtocol est une chaîne = "JSON"

// Lecture de la socket jusqu'à avoir la séquence de terminaison d'un message
// Dans notre cas, 2 RC qui se suivent
TANTQUE ChaîneOccurrence(sRequête, RC + RC) = 0
sRequête += SocketLit(Canal)
FIN
TraceTest("sRequête = "+sRequête)

// Traitement de la requête qui arrive
// La variable sRequête contient le message à traiter
// On analyse la chaîne
sClé est une chaîne ANSI
POUR TOUTE chaîne sLigne de sRequête SEPAREE PAR RC
Trace(sLigne)
SI sLigne [= ENTETE_WEBSOCKET_CLIENT ALORS
sClé = sLigne[[Taille(ENTETE_WEBSOCKET_CLIENT)+1 A]]
SINON SI sLigne [= ENTETE_WEBSOCKET_PROTOCOL
// Récupération des protocoles
ChaîneVersTableau(ExtraitChaîne(sLigne, 2, ":"), tabProtocol, ",")
FIN
FIN


// Préparation de la réponse à envoyer au client
sRes = [
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
WebSocket-Origin: <AdresseIPServeur>
WebSocket-Location: ws://<AdresseIPServeur>:5001
Sec-WebSocket-Accept: %1
]
SI tabProtocol..Occurrence <> 0 ALORS
sRes += [RC] + "Sec-WebSocket-Protocol: %2"
sProtocol = Majuscule(SansEspace(tabProtocol[1]))
sRes = ChaîneConstruit(sRes, Crypte(HashChaîne(HA_SHA_160,
sClé + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), "",
compresseAucun, encodeBASE64), sProtocol + RC + RC)

SINON
sRes = ChaîneConstruit(sRes, Crypte(HashChaîne(HA_SHA_160,
sClé + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), "",
compresseAucun, encodeBASE64) + RC + RC)
FIN

// Envoi la réponse au client
SocketEcrit(Canal, sRes)
TraceTest("SocketEcrit : "+sRes)

BOUCLE
TraceTest("************BOUCLE****************")
IF PAS SocketExiste(Canal) THEN
TraceTest("************ SORTIR ****************")
SORTIR
END
bufFrame est un Buffer = SocketLit(Canal)

TraceTest("bufFrame = "+bufFrame)
TraceTest("boucle tourne")

SI 0 = Taille(bufFrame) ALORS
Trace("Break")
TraceTest("Break")
BREAK
SINON
TraceTest("No Break")
FIN

nLongueurFrame est un entier = Asc(bufFrame[[2]]) & 127
bufMasque est un Buffer
bufDonne est un Buffer
SI 126 = nLongueurFrame ALORS
nLongueurFrame = HexaVersEntier(BufferVersHexa(bufFrame[[3 SUR 2]])) //BufferVersEntier(bufFrame, 3, 2)
bufMasque = bufFrame[[5 A 8]]
bufDonne = bufFrame[[9 A]]
SINON SI 127 = nLongueurFrame ALORS
nLongueurFrame = HexaVersEntier(BufferVersHexa(bufFrame[[3 SUR 8]]))
bufMasque = bufFrame[[11 A 14]]
bufDonne = bufFrame[[15 A]]
SINON
bufMasque = bufFrame[[3 A 6]]
bufDonne = bufFrame[[7 A]]
FIN
sTexte est une chaîne ANSI
POUR i = 1 _A_ Taille(bufDonne)
sTexte += Caract(OUExclusifBinaire( Asc(bufDonne[[i]]), Asc(bufMasque[[(i - 1) Modulo 4 + 1]])))
FIN
Trace(UTF8VersAnsi("sTexte : "+sTexte))
Trace(UTF8VersAnsi("sTexte Recu Par Client Web: "+sTexte))
TraceTest("sProtocol = " +sProtocol)
wsServeurRecuMsgParClient(sTexte)
// Formatage de la réponse
SELON sProtocol
CAS "XML"
sRes = [
<XML status="ok">
%1
</XML>
]
CAS "JSON"
sRes = [
{ "status" : "ok",
"reponse": "%1" }
]
AUTRE CAS
sRes = ChaîneVersUTF8("Format non supporté !")
FIN
//sTexte = "Votre Message est recu avec success"
sTexte = "Votre msg est : "+sTexte
sRes = ChaîneConstruit(sRes, sTexte)
TraceTest("sRes = "+sRes)

nLongueurRéponse est un entier = Taille(sRes)
bufRéponse est un Buffer
bufRéponse[[1]] = Caract(OUBinaire(0x80, ETBinaire(0x1, 0xF)))
SI nLongueurRéponse <= 125 ALORS
bufRéponse[[2]] = Caract(nLongueurRéponse)
SINON SI nLongueurRéponse <= 65536 ALORS
bufRéponse[[2]] = Caract(126)
// Manque l’écriture de la longueur
bufRéponse += HexaVersBuffer(Droite(EntierVersHexa(nLongueurRéponse), 4))
SINON
bufRéponse[[2]] = Caract(127)
// Manque l’écriture de la longueur
bufRéponse += HexaVersBuffer(EntierVersHexa(nLongueurRéponse))
FIN
SocketEcrit(Canal, bufRéponse + sRes)
TraceTest("bufRéponse = "+bufRéponse)
TraceTest("SocketEcrit : "+bufRéponse + sRes)

gsRequête = sRequête
gtabProtocol = tabProtocol
gsRes = sRes

gnLongueurFrame = nLongueurFrame
gbufMasque = bufMasque
gbufDonne = bufDonne
gnLongueurRéponse = nLongueurRéponse
gbufRéponse = bufRéponse

gsClé = sClé
FIN


Procedure wsServeurRecuMsgParClient(sMsgclient)

TraceTest("wsServeur Recu Msg Par Client : "+sMsgclient)


Procedure wsServeurEnvoiMsgAuClient(sMsg)

IF sMsg = "" THEN
RETOUR
END

n est un entier
POUR TOUT sCanal de gtabCanals
n ++
IF SocketExiste(sCanal) THEN
TraceTest("__________________Envoi Msg Au Client________________________")


//SocketEcrit(sCanal,sMsg)
//ThreadArrête(sCanal)
//SocketFerme(sCanal)
//wsEnvoiMsgACahqueCanalAvecProtocolWebSocket(sMsg,sCanal)
wsEnvoiMsgACahqueCanalAvecProtocolWebSocket(sMsg,sCanal)
//ProcédureGestioncanal(sCanal)
ELSE
TableauSupprime(gtabCanals,n)
TraceTest("Socket n'existe pas : "+sCanal+" . Canal a supprime")

END
FIN


Procedure wsEnvoiMsgACahqueCanalAvecProtocolWebSocket(sMsg,canal)

///eCode est un OpCode
bufDonnées est un Buffer //= [
// "{ "status" : "ok","reponse": "Votre msg est : text" }"
//]
//gbufDonne
vMsgServeur est un Variant
vMsgServeur.status = "ok"
vMsgServeur.reponse = sMsg
bufDonnées = VariantVersJSON(vMsgServeur)

bDernièreTrame est un booléen = Vrai

bufPayload est un Buffer

// La connexion doit être valide
//SI PAS m_bOuvert ALORS RETOUR

//
nFinBit est un octet = (bDernièreTrame ? 0x80 SINON 0x00)
bufPayload += Caract( ( nFinBit | 1) )

// Taille encodable sur 1 octet
SI Taille(bufDonnées) < 126 ALORS

nTaille est un octet = Taille(bufDonnées)
bufPayload += Caract( ( nTaille) )

// Taille encodable sur 2 octets
SINON SI Taille(bufDonnées) <= 0xFFFF

bufPayload += Caract( (126) )

nTaille est un entier sur 2 sans signe = Taille(bufDonnées)
bufPayload += HexaVersBuffer(EntierVersHexa(nTaille, 4)[[6 SUR 4]])

// Taille encodable sur 8 octets
SINON

bufPayload += Caract( (127) )

nTaille est un entier sur 8 sans signe = Taille(bufDonnées)
bufPayload += HexaVersBuffer(EntierVersHexa(nTaille, 8))
FIN

// Ajoute les données
bufPayload += bufDonnées

// Ecriture

SocketEcrit(canal, bufPayload)
SI ErreurDétectée ALORS ExceptionDéclenche(500, "Client déconnecté" + RC + ErreurInfo)
Posté le 11 décembre 2019 - 09:32
bonjour moez-wm,

je suis entrain de déployer une application webdev avec un serveur de websocket (réalisé lui en windev).

tout est ok, sauf si j’active le SSL sur le serveur IIS (version 7).

ça bloque après la fonction SocketAccepte().

au niveau de la procédure GestionCanal(), il ne lit rien !!

pour passer en SSL, j’ai utilisé SocketCréeSSL() (avec les paramètres qui vont bien je crois)

Dans le SocketConnect() du code navigateur, j’ai bien ”wss://” au lieu de ”ws://”

Avez vous une idée ?

merci d’avance !
Membre enregistré
13 messages
Popularité : +1 (1 vote)
Posté le 02 février 2021 - 15:33
bonjour moez-wm

Je suis tomber sur le tard ;( sur votre version websocket qui fonctionne très bien. J'ai juste une question sur le petit temps de latence sur l'envoi de message du serveur aux clients ( 1 à 2 secondes ) alors que le message du client au serveur et sa réponse est instantané.

Avez-vous une idée?

Cordialement
Posté le 22 février 2023 - 12:53
J'ai exactement le même problème.
Avez vous trouvé une solution?



Jean-Jacques a écrit :
bonjour moez-wm,

je suis entrain de déployer une application webdev avec un serveur de websocket (réalisé lui en windev).

tout est ok, sauf si j’active le SSL sur le serveur IIS (version 7).

ça bloque après la fonction SocketAccepte().

au niveau de la procédure GestionCanal(), il ne lit rien !!

pour passer en SSL, j’ai utilisé SocketCréeSSL() (avec les paramètres qui vont bien je crois)

Dans le SocketConnect() du code navigateur, j’ai bien ”wss://” au lieu de ”ws://”

Avez vous une idée ?

merci d’avance !