Problème Visual Basic

System.NullReferenceException : 'La référence d'objet n'est pas définie à une instance d'un objet.' MonSocketClient a été Nothing.

a marqué ce sujet comme résolu.

Bonjour, j’ai besoin d’aide pour un problème dont je ne peux imaginer l’origine:

J’écris une application Web qui va utiliser les sockets pour communiquer. J’ai un serveur qui fonctionne, le problème se pose coté client. Je me base sur un code de chat que j’adapte. La connexion au serveur se passe sans souci, l’envoi d’un pseudo passe correctement mais dès qu’il s’agit d’envoyer un message, alors que j’utilise le même sub que pour le pseudo, j’ai l’erreur suivante lors de test en local (127.0.0.1) avec IIS Express:

System.NullReferenceException : 'La référence d’objet n’est pas définie à une instance d’un objet.' MonSocketClient a été Nothing.

D’où vient le problème ?

Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

Public Class _Default
Inherits Page
'Public MonSocketClient As Socket
Public MonThread As Thread
Public Mess As Byte()
Public Envoi As Integer
Dim MonEP As IPEndPoint

Public MonSocketClient As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) 'Initialise le socket

Public Sub BT_CONNEXION_Click(sender As Object, e As EventArgs) Handles BT_CONNEXION.Click
MsgBox("ok")

Try
MonEP = New IPEndPoint(IPAddress.Parse("127.0.0.1"), 45435) 'Entre les informations de connexion
MonSocketClient.Connect(MonEP) 'Tente de se connecter
TraitementConnexion()
Catch ex As Exception
MsgBox("Erreur lors de la tentative de connexion au serveur. Vérifiez l'ip et le port du serveur." & ex.ToString, 2)
End Try
End Sub

Sub TraitementConnexion()
MsgBox("Connexion au serveur réussie !")
'Change les statuts des contrôles
BT_DECONNEXION.Visible = True
TXT_MESSAGE.Visible = True
BT_CONNEXION.Visible = False
BT_DECONNEXION.Visible = True
BT_Envoi.Visible = True

'Envoi du pseudo au serveur
envoi_Message("Alain")

MonThread = New Thread(AddressOf ThreadLecture)
MonThread.Start()
End Sub
Sub envoi_Message(TexteAEnvoyer)
Mess = Encoding.UTF8.GetBytes(TexteAEnvoyer)
Envoi = MonSocketClient.Send(Mess) 'Envoi du message au serveur
End Sub

Sub BT_Envoi_Click(sender As Object, e As EventArgs) Handles BT_Envoi.Click
MsgBox(TXT_MESSAGE.Text)
envoi_Message(TXT_MESSAGE.Text)
TXT_MESSAGE.Text = "" 'Efface la ligne

End Sub

Public Sub Deconnexion()
Me.TXT_MESSAGE.Enabled = False
Me.BT_CONNEXION.Enabled = True
Me.BT_DECONNEXION.Enabled = False
Me.BT_Envoi.Enabled = False
End Sub

Sub ThreadLecture()
While (MonSocketClient.Connected) 'Tant qu'on est connecté au serveur
Dim Bytes(255) As Byte
Dim Recu As Integer
Try
Recu = MonSocketClient.Receive(Bytes)
Catch ex As Exception 'Erreur si fermeture du socket pendant la réception
MsgBox("Connexion perdue, arrêt de la réception des données ...", 1)
'If Not Me.IsDisposed Then 'Si ce n'est pas le client qui est en cours de fermeture
'Me.Invoke(New dDeconnexion(AddressOf Deconnexion))
'End If
End Try
Dim Message As String
Message = System.Text.Encoding.UTF8.GetString(Bytes)
Message = Message.Substring(0, Recu)
'Dim Temp As String = TXT_MESSAGES.Text
'Message = Temp + Message
TXT_MESSAGES.Text = Message
'TXT_MESSAGES.Items.Add(Message)
MsgBox(Message)
End While
End Sub

End Class

Merci pour votre aide

+0 -0

Si je comprends bien y’a une ouverture du socket, un envoi du pseudo Alain vers le serveur et l’attente du message. C’est bien dans la méthode ThreadLecture que ça plante ? Quelle ligne précisément ?

Yarflam

pas exactement: l’envoi du pseudo passe, le serveur envoie une confirmation de connexion que je reçois mais après les messages vers le serveur (sub envoi_Message()) ne passent pas ….

Nouveaux essai ce matin (simplement ajouté une ligne après lecture du message reçu pour vérifier que le socket est toujours connecté: Dim x = MonSocketClient.Connected() MsgBox(x)

et nouveau message d’erreur : Une requête d’envoi ou de réception de données n’a pas été autorisée car le socket n’est pas connecté et (lors de l’envoi sur un socket datagramme en utilisant un appel sendto) aucune adresse n’a été fournie

+0 -0

Etant sur Linux, les technos .NET ne sont pas prises en charge - il m’est difficile de tester.

Je pense qu’il s’agit d’un problème au moment de la création du Thread. Le programme quitte l’instance du bouton (méthode BT_CONNEXION_Click) après avoir envoyé le pseudo, ça pourrait peut-être "geler" la variable MonSocketClient. Je te recommande de créer une classe à part réservé à la gestion du Socket et garder seulement dans cette classe, les méthodes liées à l’interface (BT_CONNEXION_Click et BT_Envoi_Click). Au lieu d’utiliser MonSocketClient directement, tu appelles l’instance de ta nouvelle classe.

Public Class _Default
    Inherits Page
    Public CustomThread As ThreadManager = New ThreadManager() 'Instance de la nouvelle classe
    
    Public Sub BT_CONNEXION_Click(sender As Object, e As EventArgs) Handles BT_CONNEXION.Click
      If CustomThread.connexion("127.0.0.1", 45435) = True Then 'Connexion au Socket
        CustomThread.envoyer_message("Alain") 'Envoyer un premier message
        CustomThread.lecture() 'Réception des messages (création d'un Thread depuis la méthode `lecture`)
      Else
        MsgBox("Problème de connexion")
      End If
    End Sub
    
    Sub BT_Envoi_Click(sender As Object, e As EventArgs) Handles BT_Envoi.Click
      MsgBox(TXT_MESSAGE.Text)
      CustomThread.envoyer_message(TXT_MESSAGE.Text)
      TXT_MESSAGE.Text = "" 'Efface la ligne
    End Sub
End Class

edit : oups j’avais mis des ";" en fin de ligne (déformation professionnelle dû à l’utilisation intensive du Javascript :p )

+1 -0

Etant sur Linux, les technos .NET ne sont pas prises en charge - il m’est difficile de tester.

Je pense qu’il s’agit d’un problème au moment de la création du Thread. Le programme quitte l’instance du bouton (méthode BT_CONNEXION_Click) après avoir envoyé le pseudo, ça pourrait peut-être "geler" la variable MonSocketClient. Je te recommande de créer une classe à part réservé à la gestion du Socket et garder seulement dans cette classe, les méthodes liées à l’interface (BT_CONNEXION_Click et BT_Envoi_Click). Au lieu d’utiliser MonSocketClient directement, tu appelles l’instance de ta nouvelle classe.

merci, je teste et te dis ce qu’il es est …

Public Class _Default
    Inherits Page
    Public CustomThread As ThreadManager = New ThreadManager() 'Instance de la nouvelle classe
    
    Public Sub BT_CONNEXION_Click(sender As Object, e As EventArgs) Handles BT_CONNEXION.Click
      If CustomThread.connexion("127.0.0.1", 45435) = True Then 'Connexion au Socket
        CustomThread.envoyer_message("Alain"); 'Envoyer un premier message
        CustomThread.lecture(); 'Réception des messages (création d'un Thread depuis la méthode `lecture`)
      Else
        MsgBox("Problème de connexion");
      End If
    End Sub
    
    Sub BT_Envoi_Click(sender As Object, e As EventArgs) Handles BT_Envoi.Click
      MsgBox(TXT_MESSAGE.Text)
      CustomThread.envoyer_message(TXT_MESSAGE.Text)
      TXT_MESSAGE.Text = "" 'Efface la ligne
    End Sub
End Class

Yarflam

Il semble bien que tu aies vu juste, j’ai vérifié l’état de la connexion du socket : après réception du message, donc avant le click Bouton : true après le click bouton : false.

Me faut maintenant comprendre comment implémenter ta solution merci

Public CustomThread As ThreadManager = New ThreadManager() 'Instance de la nouvelle classe

Threadmanager n’existe pas ici ….

En fait, mon problème est tout simple : le client clique sur un bouton, un message prédéfini est envoyé au serveur qui le renvoie à tous les clients ….

J’ai fait beaucoup d’ASP et de JavaScript, mais j’avoue que, ici, je suis perdu (depuis 2 mois)

Merci pour ton aide

Public CustomThread As ThreadManager = New ThreadManager() 'Instance de la nouvelle classe

Threadmanager n’existe pas ici ….

Alain Elshocht

Tout à fait, puis-ce qu’il s’agit de créer une nouvelle classe pour déporter l’instance MonSocketClient.

Quelque chose comme ça :

Imports System.Net
Imports System.Net.Sockets
Imports System.Threading

Public Class ThreadManager
  Public MonThread As Thread
  Public Mess As Byte()
  Public Envoi As Integer
  Dim MonEP As IPEndPoint
  
  Public MonSocketClient As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
  
  Public Sub connexion(host, port) As Boolean
    Try
      MonEP = New IPEndPoint(IPAddress.Parse(host), port)
      MonSocketClient.Connect(MonEP)
      return true
    Catch ex As Exception
      return false
    End Try
  End Sub

  Public Sub envoyer_message(message)
    Mess = Encoding.UTF8.GetBytes(message)
    Envoi = MonSocketClient.Send(Mess)
  End Sub
    
  Public Sub lecture()
    MonThread = New Thread(AddressOf ThreadLecture)
    MonThread.Start()
  End Sub

  Public Sub ThreadLecture()
    While (MonSocketClient.Connected)
      Dim Bytes(255) As Byte
      Dim Recu As Integer

      Try
        Recu = MonSocketClient.Receive(Bytes)
      Catch ex As Exception
        MsgBox("Connexion perdue, arrêt de la réception des données ...", 1)
      End Try

      Dim Message As String
      Message = System.Text.Encoding.UTF8.GetString(Bytes)
      Message = Message.Substring(0, Recu)
      MsgBox(Message)
    End While
  End Sub
End Class

D’ailleurs on pourrait plutôt l’appeler SocketManager plutôt que ThreadManager. Après j’ai peut-être fait des erreurs d’implémentations ; n’ayant ni l’environnement ni toutes les subtilités du VB.NET, je pourrai difficilement t’aider plus que ça.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte