Interaction Silverlight coté client et php coté serveur

Silverlight permet de créer des applications web à moindre coût.

Visual Web Developer 2010 Express est gratuit en téléchargement.
Version française : http://www.microsoft.com/express/downloads/
Le “Tools Kit” Silverlight :
Version française : http://www.microsoft.com/downloads/details.aspx?familyid=EFF8A0DA-0A4D-48E8-8366-6DDF2ECAD801&displaylang=fr

Une application Silverlight s’exécute coté client bien entendu. (Win et Mac)
Elle sera hébergée sur un serveur LAMP.
Pour faire communiquer plusieurs clients Silverlight entre eux nous utiliserons le protocole HTTP + deux scripts PHP.
Un script pour écrire les messages et un autre pour les lire.

Pour illustrer ce principe voilà donc un chat Silverlight + PHP léger.

L’application sera écrite en Visual Basic.

Le nom de l’application : ChatSL2phpVB

1. Description de l’application
L’interface sera constituée des éléments suivants :
- TextBox pour inscrire son Pseudo
- TextBox pour saisir les messages
- ScrollViewer pour afficher les messages

Un aperçu de l’interface :

2. Principe général
On utilisera l’objet WebClient pour la communication HTTP

Ecriture d’un message :
Client SL -> WebClient -> POST « data » -> write_msg.php : écriture dans un dossier « /msg » d’un fichier référencé temporellement (timestamped) sur le serveur
Retour HTTP : 0

Relever un message :
Client SL -> WebClient -> read_msg.php : lecture de tous les fichiers « timestamped »
Retour HTTP : fichier si non encore lu ou nothing

Le Script write_msg.php :

<?php
if (isset($_POST["user"]))
{
list($usec, $sec) = explode( » « , microtime());
$ts = $sec.substr($usec,2,4);
// On crée le fichier message dans le dossier msg
$fichier = fopen(‘msg/’.$ts, ‘w+’);
fwrite($fichier, stripslashes($_POST['data']));
fclose($fichier);
echo « 0″;
$dossier = opendir(‘msg’);
while ($fichier = readdir($dossier))
{
if (!preg_match(« #^[.]{1,2}[a-z0-9 -.]*#i »,$fichier))
{
// On en profite pour purger les msg plus vieux que 15 secondes
if ($fichier < ($ts – 150000))
{
unlink(‘msg/’.$fichier);
}
}
}
closedir($dossier);
}
?>

Le script read_msg.php :

<?php
session_start();
// ouvrir le dosssier msg
$dossier = opendir(‘msg’);

while ($fichier = readdir($dossier))
{
if (!preg_match(« #^[.]{1,2}[a-z0-9 -.]*#i »,$fichier))
{
$files_array[] = $fichier;
}
}
closedir($dossier);

sort($files_array);

foreach ($files_array as $key => $val)
{
if ($_SESSION['last_msg_ts'] < $val)
{
// Lit le message non lu
readfile(‘msg/’.$val,’r');
// Indique le dernier message lu
$_SESSION['last_msg_ts'] = $val;
exit;
}
}
?>

3. Poster un message avec WebClient
Les données sont envoyées de manière asynchrone avec une requête POST.
Suite à l’appui du bouton Send :
- Stop à la réception des messages
- Transmission au script write_msg.php les paramètres « user » et « data ».
- Attente du retour serveur de la valeur « 0″, puis relance de la réception des messages.
Coté serveur :
- écriture du fichier référencé temporellement par rapport à l’heure du serveur
- vérification des vieux messages présents dans le dossier ‘/msg’.
- S’il sont plus vieux de 15 secondes on les supprime.

Private Sub SendMsg(ByVal Data As String)

ReadMsgTmr.Stop()

Try
Dim Client As New WebClient()
Client.Headers(« Content-Type ») = « application/x-www-form-urlencoded »
AddHandler Client.UploadStringCompleted, AddressOf SendMsgCompleted
Client.UploadStringAsync(New Uri(String.Format(« {0}/write_msg.php »,
BASEPATH)),    « Post », « user= » & UsrTbx.Text & « &data= » & Data)

Catch ex As Exception

End Try

End Sub

Private Sub SendMsgCompleted(ByVal sender As Object, _
ByVal e As UploadStringCompletedEventArgs)

Try
Dim Msg As String = e.Result
Select Case Msg
Case Nothing
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1)
ReadMsgTmr.Start()
Exit Sub
Case « 0″
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1)
ReadMsgTmr.Start()
End Select
Catch ex As Exception

End Try

End Sub

4. Lire un message avec WebClient
Le relevé des messages est fait de façon périodique selon la logique suivante :
Mode « Idle » :
- Toute les 1,5 seconde
Mode « Rafale » :
- Toute les 0,15 seconde
Mode « After Writing » :
- Aussitot après avoir posté un message

Nota : on aurait pu imaginer un « LongIdle » de 3 secondes pour les périodes d’inactivité … longue.

Private Sub ReadMsgTmr_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ReadMsgTmr.Tick

ReadMsgTmr.Stop()

Try

Dim Client = New WebClient
AddHandler Client.DownloadStringCompleted, AddressOf ReadMsgComplete
Client.DownloadStringAsync(New Uri(Config.BASEPATH & « /read_msg.php », UriKind.Absolute), 0)

Client = Nothing

Catch ex As Exception
‘HtmlPage.Window.Alert(ex.Message)
End Try

End Sub

Private Sub ReadMsgComplete(ByVal sender As Object, _
ByVal e As DownloadStringCompletedEventArgs)
Try
‘ Si il y a un message
Dim Msg As String = e.Result
If Msg <> «  » Then DisplayTextinChatBox(Msg)
‘ raffale
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(150)
Else
‘ idle
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1500)
End If

Catch ex As Exception

End Try
ReadMsgTmr.Start()

End Sub

5. Déployer
Un simple copier coller des fichiers via ftp, on change le CHMOD du dossier « msg » à 777 et voilà :)

6. Annexes
Le code VB complet :

Imports System.IO.IsolatedStorage
Imports System.Windows.Threading

Partial Public Class MainPage
Inherits UserControl
Private AppSetting As IsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings
Private WithEvents ReadMsgTmr As New DispatcherTimer
Private Smoke As Boolean
Private BASEPATH As String = «  » ‘ « http://www.monsite.fr/MiniChat » ‘Test path
Private Client As New WebClient

Public Sub New()
InitializeComponent()
AddHandler Client.DownloadStringCompleted, AddressOf ReadMsgComplete
ReadMsgTmr.Interval = TimeSpan.FromMilliseconds(1500)
If AppSetting.Keys.Count > 0 Then
For Each Key In AppSetting.Keys
Select Case Key.ToString
Case « UserName »
If AppSetting(« UserName »).ToString <> «  » Then
UsrTbx.Text = AppSetting(« UserName »).ToString
End If
End Select
Next
End If
MsgTbx.Focus()
ReadMsgTmr.Start()

‘Dim Src As System.Uri = Application.Current.Host.Source
If BASEPATH = «  » Then
Dim uri As String = Application.Current.Host.Source.AbsoluteUri
uri = uri.Substring(0, uri.IndexOf(« /ChatSL2phpVB.xap »))
BASEPATH = uri ‘ : SendMsg(uri)
‘supprimez la ligne ci dessous pour compiler une version déployable
BASEPATH = « http://www.furukoo.fr/MiniChat »
End If

End Sub

Public Sub DisplayTextinChatBox(ByVal Msg As String)

If Msg Is Nothing Then Exit Sub
 » Crée un TextBlock
Dim Tbl As New TextBox
With Tbl
.Text = Msg
.TextWrapping = TextWrapping.Wrap
.IsReadOnly = True
.Style = DirectCast(Me.Resources(« ChatStyle »), Windows.Style)
If Smoke Then
.Background = New SolidColorBrush(Color.FromArgb(255, 248, 248, 248))
Smoke = False
Else
Smoke = True
End If
End With

With MsgSpl.Children
 » Limite le nombre de messages dans la ListBox
If .Count > 50 Then .RemoveAt(50)
.Insert(0, Tbl)
End With

‘ Déplace l’ascenseur vers le haut
MsgSvr.ScrollToVerticalOffset(0)

End Sub

Private Sub SendMsg(ByVal Data As String)

ReadMsgTmr.Stop()

Try
Dim Client As New WebClient()
Client.Headers(« Content-Type ») = « application/x-www-form-urlencoded »
AddHandler Client.UploadStringCompleted, AddressOf SendMsgCompleted
Client.UploadStringAsync(New Uri(String.Format(« {0}/write_msg.php », BASEPATH)), _
« Post », _
« user= » & UsrTbx.Text & « &data= » & Data)

Catch ex As Exception

End Try

End Sub

Private Sub SendMsgCompleted(ByVal sender As Object, _
ByVal e As UploadStringCompletedEventArgs)

Try
Dim Msg As String = e.Result
Select Case Msg
Case Nothing
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1)
ReadMsgTmr.Start()
Exit Sub
Case « 0″
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1)
ReadMsgTmr.Start()
End Select
Catch ex As Exception

End Try

End Sub

Private Sub ReadMsgTmr_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles ReadMsgTmr.Tick

ReadMsgTmr.Stop()

Try

Client.DownloadStringAsync(New Uri(BASEPATH & « /read_msg.php », UriKind.Absolute), 0)

Catch ex As Exception
‘HtmlPage.Window.Alert(ex.Message)
End Try

End Sub

Private Sub ReadMsgComplete(ByVal sender As Object, _
ByVal e As DownloadStringCompletedEventArgs)
Try
‘ Si il y a un message
Dim Msg As String = e.Result
If Msg <> «  » Then
DisplayTextinChatBox(Msg)
‘ raffale
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(150)
Else
‘ idle
ReadMsgTmr.Interval = System.TimeSpan.FromMilliseconds(1500)
End If

Catch ex As Exception

End Try
ReadMsgTmr.Start()

End Sub

Private Sub MsgTbx_GotFocus(ByVal sender As Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles MsgTbx.GotFocus
MsgTbx.Text = «  »
MsgTbx.Focus()

End Sub

Private Sub MsgTbx_KeyUp(ByVal sender As System.Object, _
ByVal e As System.Windows.Input.KeyEventArgs) Handles MsgTbx.KeyUp
Select Case e.Key
Case Key.Enter
If MsgTbx.Text = «  » Then MsgTbx.Focus() : Exit Sub
SendMsg(UsrTbx.Text &  » :  » & MsgTbx.Text)
MsgTbx.Text = «  »
MsgTbx.Focus()
Case Else
Exit Sub
End Select
End Sub

Private Sub UsrTbx_TextChanged(ByVal sender As Object, _
ByVal e As System.Windows.Controls.TextChangedEventArgs) _
Handles UsrTbx.TextChanged

AppSetting(« UserName ») = UsrTbx.Text
AppSetting.Save()

End Sub

End Class

7. Testez en direct
Vous pouvez tester ce Mini Chat ici

Les sources disponible ici

Share this Post:
Digg Google Bookmarks reddit Mixx StumbleUpon Technorati Yahoo! Buzz DesignFloat Delicious BlinkList Furl

13 Responses to “Interaction Silverlight coté client et php coté serveur”

commenter

I must admit this post is very wonderful . Thanks once again for the push!

commenter

Its great that you Shed light on a few things I didn’t understand. Thank you , hope you can keep writing blog,2

commenter

acai berry has helped many to reduce their weight with very less efforts.

commenter

ce que je cherchais, merci

commenter

J’aime bien cet article mais tu devrais mieux argumenter la seconde partie, c’est selon moi trop léger. Bonne continuation !

commenter

J’ai trouvé ce blog il y a 1 heure et et je ne peux plus en décrocher , merci

Leave a Reply:

Name (required):
Mail (will not be published) (required):
Website:
Comment (required):
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>