sniceper
Messages postés19Date d'inscriptiondimanche 14 août 2005StatutMembreDernière intervention20 septembre 2010
-
9 oct. 2008 à 18:36
Kevin.Ory
Messages postés840Date d'inscriptionmercredi 22 octobre 2003StatutMembreDernière intervention 7 janvier 2009
-
10 oct. 2008 à 20:33
Bonsoir, je suis actuellement face à une énigme dérangeante.
En effet, j'ai programmé un serveur simpliste en utilisant system.net.sockets.
Or, il s'est vite avéré que mon serveur plantait dès que je tentais de le mettre en écoute.
Pour tenter de réparer le problème, j'ai coutume de mettre des msgbox un peu partout ( sa permet de cibler un peu plus le problème).
Et là, c'est le drame!
Lorsque mon programme est blindé de msgbox, il fonctionne au poil, alors quil se remet a planter dès que je les enlève. Je me suis dit que certaines commandes du sockets necessitaient un peu de temps à s'executer et que les msgbox lui offrait ce temps, idée stupide que j'ai abandonné que j'ai remarqué que le programme plantait toujours autant lorsque je remplaçais les fameuses msgbox par des sleep().
Je commence à desesperer, et toute réponse est plus que bienvenue, merci d'avance.
Public Class Form1
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim server As TcpListener
server = Nothing
MsgBox("plop")
Dim port As Int32
port = Val(TextBox1.Text.ToString)
MsgBox("plop")
Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
server = New TcpListener(localAddr, port)
MsgBox("plop")
server.Start()
Button1.Enabled = False
MsgBox("plop")
Dim bytes(1024) As Byte
Dim data As String = Nothing
MsgBox("plop")
Dim contenu As String = "rien"
Label1.Text = "Ecoute lancée, en attente... "
MsgBox("plop")
Label1.ForeColor = Color.Blue
MsgBox("plop")
Dim client As TcpClient = server.AcceptTcpClient()
Label1.Text = "Connecté"
Label1.ForeColor = Color.Green
Console.Beep(40, 100)
Console.Beep(60, 100)
Dim stream As NetworkStream = client.GetStream()
Dim i As Int32
While contenu <> "/quit"
Try
data = Nothing
i = stream.Read(bytes, 0, bytes.Length)
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
contenu = data.ToString
If contenu <> "/quit" Then
MsgBox("message reçu: " & data.ToString)
End If
Catch
MsgBox("Connexion avec l'hôte perdue !", MsgBoxStyle.Critical)
contenu = "/quit"
End Try
End While
server.Stop()
Me.Close()
End Sub
End Class
Kevin.Ory
Messages postés840Date d'inscriptionmercredi 22 octobre 2003StatutMembreDernière intervention 7 janvier 200911 10 oct. 2008 à 13:51
"Effectivement le programme ne repond plus, mais il n'a meme pas le
temps d'executer la ligne "label1.text=Ecoute lancée, en attente..."
car le label ne change pas de tête."
Si si, la ligne label1.text=Ecoute lancée, en attente...est forcément exécuté, seulement tu ne le vois pas
Vu que ton code qui suit cette ligne est bloquant, l'affichage ne se met pas à jour et donc on ne voit pas le texte de label1 changer
Une solution serait de faire un DoEvents après cette ligne, ce qui mettrait l'affichage à jour avant d'entrer dans une fonction bloquante, mais il faut avouer que ma technique du message précédent est bien meilleur (pas de "Ne répond plus", possibilité d'annuler l'écoute, début pour pouvoir accepter plusieurs clients, etc...)
Et d'ailleurs, c'est pour ça que ton code semble mieux fonctionner lorsque tu utilise des MessageBox, car l'affichage de ton formulaire principal est rafraichit lorsque on affiche une MessageBox
sniceper
Messages postés19Date d'inscriptiondimanche 14 août 2005StatutMembreDernière intervention20 septembre 2010 9 oct. 2008 à 18:56
Avec plaisir, mais quand je poste, tous les retour chariots et les tabulation que je met a mon code se barrent. pour faire cet infâme paté. quelque chose de particulier a faire pour ne pas que cela soit ignoré?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Kevin.Ory
Messages postés840Date d'inscriptionmercredi 22 octobre 2003StatutMembreDernière intervention 7 janvier 200911 10 oct. 2008 à 00:31
"moi je copy paste directement depuis vb2005 dans la freetextbox et ça fonctionne très bien mais il y a aussi"
Très bien tu dis? Avec ces suppressions d'espaces et ces retours à la ligne non voulu, c'est franchement désagréable de lire un code, en tout cas moi j'ai horreur de ça
Moi je conseil un copier-coller en passant par le bloc-note, ça permet de supprimer toutes les mises en forme.
Mais j'ajoute quand même que lorsque je fais un copier-coller depuis l'IDE de VB, ça ne me donne pas un gros bloc comme ceci, toutefois tu n'es pas le seul à qui ça arrive.
Private Sub Button1_Click(...) Handles Button1.Click
Button1.Enabled = False
Dim server As TcpListener
Dim port As Int32 = Val(TextBox1.Text.ToString)
Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1")
server = New TcpListener(localAddr, port)
server.Start()
Dim bytes(1024) As Byte
Dim data As String = Nothing
Dim contenu As String = "rien"
Label1.Text = "Ecoute lancée, en attente... "
Label1.ForeColor = Color.Blue
Dim client As TcpClient = server.AcceptTcpClient()
Label1.Text = "Connecté"
Label1.ForeColor = Color.Green
Dim stream As NetworkStream = client.GetStream()
Dim i As Int32
While contenu <> "/quit"
Try
i = stream.Read(bytes, 0, bytes.Length)
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
contenu = data.ToString
If contenu <> "/quit" Then
MsgBox("message reçu: " & data.ToString)
End If
Catch
MsgBox("Connexion avec l'hôte perdue !", MsgBoxStyle.Critical)
contenu = "/quit"
End Try
End While
server.Stop()
Me.Close()
End Sub
End Class
sniceper>
"Or, il s'est vite avéré que mon serveur plantait dès que je tentais de le mettre en écoute"
J'ai envie de poser la question suivante: que veux-tu dire par "planter" ?
Si tu veux dire par là que ton application ne répond plus, c'est absolument normal puisque server.AcceptTcpClient() et stream.Read() sont des fonctions bloquantes, même chose pour un Sleep. Pour résoudre ce problème, il faut soit utiliser les fonctions non-bloquantes (server.BeginAcceptTcpClient et stream.BeginRead) ou utiliser un 2ème thread pour la lecture.
sniceper
Messages postés19Date d'inscriptiondimanche 14 août 2005StatutMembreDernière intervention20 septembre 2010 10 oct. 2008 à 13:32
oui je suis d'accord, mais le problème ne vient pas de là.
Effectivement le programme ne repond plus, mais il n'a meme pas le temps d'executer la ligne "label1.text=Ecoute lancée, en attente..." car le label ne change pas de tête. A moins que "server = New TcpListener(localAddr, port)
server.Start()" ne soit bloquant aussi?
Et merci beaucoup pour la remise en page, c'est tres sympa.
Kevin.Ory
Messages postés840Date d'inscriptionmercredi 22 octobre 2003StatutMembreDernière intervention 7 janvier 200911 10 oct. 2008 à 13:43
Regarde ce code, tapé à la va-vite et pas testé, mais je crois qu'il devrait fonctionner:
Imports System.Net
Imports System.Net.Sockets
Public Class Form1
Private WithEvents Worker As New System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Lancer l'écouteur dans un thread en arrière-plan
Worker.WorkerReportsProgress = True
Worker.RunWorkerAsync(Val(TextBox1.Text.ToString))
End Sub
Private Sub Worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Worker.DoWork
' Ecouter les connexions entrantes
Dim listener As New TcpListener(IPAddress.Parse("127.0.0.1"), e.Argument)
listener.Start()
' Accepter un client
Dim Client As TcpClient = listener.AcceptTcpClient()
Dim Stream As NetworkStream = Client.GetStream
Dim Buffer(Client.ReceiveBufferSize - 1) As Byte
' Lire les messages entrants
Do
Dim Len As Integer = Stream.Read(Buffer, 0, Buffer.Length)
Dim Message As String = System.Text.Encoding.ASCII.GetString(Buffer, 0, Len)
If Message <> "/quit" Then
Worker.ReportProgress(0, Message)
Else
Exit Do
End If
Loop
End Sub
Private Sub Worker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles Worker.ProgressChanged
' Afficher un message reçu
MsgBox(e.UserState)
End Sub
End Class
Une limitation avec ce code, c'est que si un message fait plus de 'Client.ReceiveBufferSize'caractères (c'est à dire la taille du buffer de réception), les données seront coupés en plusieurs messages.
On peut aussi utiliser un BinaryReader pour lire les données reçue, ce qui simplifie la choses et élimine la limitation de l'autre technique, mais je crois que le fonctionnement n'est pas le même (à vérifier, codage du texte <> ASCII !):
Private Sub Worker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Worker.DoWork
' Ecouter les connexions entrantes
Dim listener As New TcpListener(IPAddress.Parse("127.0.0.1"), e.Argument)
listener.Start()
' Accepter un client
Dim Client As TcpClient = listener.AcceptTcpClient()
Dim Reader As New IO.BinaryReader(Client.GetStream)
sniceper
Messages postés19Date d'inscriptiondimanche 14 août 2005StatutMembreDernière intervention20 septembre 2010 10 oct. 2008 à 17:09
okayyyy!!! fiew c'est bon je capte le principe.
Effectivement utiliser le listener en arriere plan et je vois a peu pres comment l'adapter pour la connexion multi-client.
Merci beaucoup de la précision et la clarté de tes explications.
(je me ferais jamais à la sympathie des gens sur ce forum ^^)