Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1925 connectés 

  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  Problème Vb.Net TCP/IP

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Problème Vb.Net TCP/IP

n°1597632
backdafuck​up
Back to da old skool
Posté le 09-08-2007 à 12:01:15  profilanswer
 

Bonjour,
 
Mon problème va être un peu long a être expliqué, mais j'espère que les plus vaillants pour répondre.
 
Le schéma est simple.
La ou je travaille, il y a une porte avec un lecteur de badge (lecteur simple à code barre). Ce lecteur est relié à notre réseau en ethernet, et communique avec le serveur sur le protocole TCP, sur le port 2100.
 
Le serveur possède plusieurs services, qui répondent au lecteur en tant voulu.
Après quelques sniff du réseau, j'ai trouvé les infos envoyées, les échanges etc.
 
Le but de mon projet est de développer une appli de remplacement pour gérer les badges, la communication, tout ça, étant donné que l'appli actuelle est sous un vieux NT4, et on a très peur d'une panne matérielle, entre autres.
 
Donc je me suis intéressé à la programmation TCP/IP en vb.net, puisque j'avais ça sous la main et que je m'en sortais pas trop mal.
 
J'ai commencé par faire une appli serveur qui écoute le port 2100 en asynchrone (pour rien bloquer). Je reçois correctement les informations.
Mais, il faut répondre. Pourquoi ? 2 raisons :  
 
- Le lecteur, lorsque qu'un badge est lu, envoie un paquet TCP qui contient une chaine de 49 caractères, avec dedans le matricule du badge, l'identificaiton du lecteur, la date et l'heure (plus quelques autres chiffres toujours identiques).
- De temps en temps (je n'ai pas trouvé de récurrence pour l'instant), le lecteur envoie un message de la forme *011100000000m et attend une réponse valant :008100012v avec les caractères 0A 0D à la fin (CR et LF).
 
Après une longue analyse, je commence à mieux comprendre les paquets TCP.
Le lecteur envoie dans son paquet (comme tout paquet tcp je suppose), trois infos importantes : le numéro de séquence, le prochain numéro de séquence et le numéro d'accusé de réception (ACK).
Je pense (et surtout dites moi si je me trompe), que la réponse doit avoir pour séquence le numéro "next sequence" du lecteur. Mais ce n'est pas le cas dans ce que je renvoie...
Un exemple
 
Lecteur
-------
Sequence : 1234
Next Sequence : 65473
ACK : 25
 
Serveur
--------
Sequence : 2514
Next Sequence : XXXXX (on s'en fout)
ACK : 1234
 
Il me semble que c'est pas bon, et que c'est pour ça que la communication ne se fait pas. En fait, on dirait que le lecteur n'entend pas ma réponse.
 
J'aimerais juste arriver à ce qu'elle capte mon message, que je puisse lui répondre immédiatement, dès que je reçois son message, mais là, je sèche...
 
Voici mon code (juste pour la réception et émission de message) :  
 

Code :
  1. Dim networkStream As NetworkStream = Me.tcpClient.GetStream()
  2.             ' Read the stream into a byte array
  3.             Dim bytes(Me.tcpClient.ReceiveBufferSize) As Byte
  4.             networkStream.Read(bytes, 0, CInt(Me.tcpClient.ReceiveBufferSize))
  5.             ' Return the data received from the client to the console.
  6.             Dim clientdata As String = Encoding.ASCII.GetString(bytes)
  7.             clientdata = Replace(clientdata, Chr(0), "" )
  8.             clientdata = Replace(clientdata, Chr(10), "" )
  9.             clientdata = Replace(clientdata, Chr(13), "" )
  10.             Me.CallDisplayMessage("Client sent: " & clientdata)
  11.             Dim Reponse() As Byte = GetReponse(clientdata)
  12.             Me.CallDisplayMessage("Host sending: " & Encoding.ASCII.GetString(Reponse))
  13.             Dim sendBytes As [Byte]() = Reponse
  14.             networkStream.Write(sendBytes, 0, sendBytes.Length)


 
La connexion se fait bien, ça fonctionne puisque j'avais fait des tests avec une appli cliente qui simulait le lecteur, et ça communique correctement.
Dès que je communique avec le lecteur, il ne reçoit pas mes messages...
 
Voilà, si quelqu'un peut m'aider, ça serait génial...
 
Merci d'avance

mood
Publicité
Posté le 09-08-2007 à 12:01:15  profilanswer
 

n°1597662
moi23372
Posté le 09-08-2007 à 13:18:17  profilanswer
 

de 1, je te conseille de te documenter directement sur le lecteur. Il doit surement y avoir quelques part une doc expliquant comment celui ci fonctionne et quel message il peut recevoir/envoyer...
 
ensuite, ce qui me gène un peu, c'est que tu veux gérer toi même les numéro de séquence et les numéro ack.  
Or si tu es bien en TCP/IP, c'est le protocole qui se charge de faire cela pour toi...
 
Par contre, si tu es en UDP, c'est à toi de gérer cela...  
Visisblement, tu es bien en TCP... donc tu ne dois pas t'en préoccuper.  
 
Maintenant, si tu as réussi à sniffer les paquets initiaux avec l'ancien programme, tu dois pouvoir les analyser plus précisement et comprendre peut être pourquoi ton lecteur ne réagi pas.

n°1597668
backdafuck​up
Back to da old skool
Posté le 09-08-2007 à 13:33:03  profilanswer
 

moi23372 a écrit :

de 1, je te conseille de te documenter directement sur le lecteur. Il doit surement y avoir quelques part une doc expliquant comment celui ci fonctionne et quel message il peut recevoir/envoyer...
 
ensuite, ce qui me gène un peu, c'est que tu veux gérer toi même les numéro de séquence et les numéro ack.  
Or si tu es bien en TCP/IP, c'est le protocole qui se charge de faire cela pour toi...
 
Par contre, si tu es en UDP, c'est à toi de gérer cela...  
Visisblement, tu es bien en TCP... donc tu ne dois pas t'en préoccuper.  
 
Maintenant, si tu as réussi à sniffer les paquets initiaux avec l'ancien programme, tu dois pouvoir les analyser plus précisement et comprendre peut être pourquoi ton lecteur ne réagi pas.


 
Ben justement, je ne comprends pas.
Pour répondre à ton 1, je n'ai pas trouvé de doc. J'ai une doc donnée lors de l'achat de la machine et du logiciel gestionnaire mais rien sur la communication. J'ai piétinné sur ce point, et c'est pour ça que j'ai cherché à sniffer.
 
Et dans les sniffs, rien de plus que ce que j'ai expliqué, à moins que je devienne aveugle (je peux éventuellement poster des logs de sniffs si qqn veut).
 
Je ne veux pas forcément les gérer, mais j'aimerais déjà savoir si le fonctionnement que j'ai décrit est normal...
 
Merci

n°1598034
backdafuck​up
Back to da old skool
Posté le 10-08-2007 à 08:52:54  profilanswer
 

:bounce:

n°1599868
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 08:51:07  profilanswer
 

Après une longue période d'analyse, j'ai enfin trouvé mon problème.
 
Mon application, en fait, n'a pas de problème au niveau TCP/IP.
Mon serveur reçoit correctement les messages, et répond correctement (enfin presque).
 
Pour rappel, mon code fonctionne de la façon suivante :  
 

Code :
  1. 'Arret ecoute'
  2. Me.tcpClient = Me.tcpListener.EndAcceptTcpClient(async)
  3. 'Traitement de la réponse'
  4. ...
  5. 'Fin traitement de la réponse'
  6. 'Relance écoute'
  7. Me.tcpListener.BeginAcceptTcpClient(AddressOf Me.ReceiveCallBackMessage, Me.tcpListener)


 
Donc, entre l'arrêt et le redémarrage de l'écoute, le serveur est sourd. Le problème, c'est que le client n'est pas muet de son coté, et il envoie, dans ce laps de temps, d'autres paquets, qui sont donc perdus.
 
Dans les logs du sniff que j'ai fait, j'ai donc des packet loss, et des questions sans réponses (pour le client).
C'est pour ça que la communication n'est pas complète.
 
Alors je cherche un peu partout sur le net une façon d'arrêter l'écoute, puis de la reprendre immédiatement (l'arrêt de l'écoute est obligatoire avec ces méthodes asynchrones).
 
J'ai essayé pas mal de choses : relancer l'écoute avant le traitement de la réponse, relancer l'écoute dans un thread que je créée manuellement, etc etc...
 
Si quelqu'un pouvait m'aider, ça serait génial.
 
Merci d'avance !

n°1599910
moi23372
Posté le 16-08-2007 à 10:41:21  profilanswer
 

tu ne dois surtout pas arreter l'écoute...
 
tu es ici en mode connecté. Une fois que la connexion est établie entre le client et le serveur, tu ne dois pas couper la connexion sauf quand tu arretes ton serveur ou que le client se déconnecte par lui même...
 
Pour cela, tu dois travailler avec des threads et boucler sur les messages du client tout simplement.  
 
Si tu ne fais pas ça, tu n'y arrivera jamais

n°1599918
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 10:56:49  profilanswer
 

moi23372 a écrit :

tu ne dois surtout pas arreter l'écoute...
 
tu es ici en mode connecté. Une fois que la connexion est établie entre le client et le serveur, tu ne dois pas couper la connexion sauf quand tu arretes ton serveur ou que le client se déconnecte par lui même...
 
Pour cela, tu dois travailler avec des threads et boucler sur les messages du client tout simplement.  
 
Si tu ne fais pas ça, tu n'y arrivera jamais


 
Donc ne pas utiliser les méthodes BeginAccept et EndAccept, mais plutot lancer manuellement des threads et boucler sur l'écoute ?

n°1599939
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 11:32:20  profilanswer
 

'Tain je galère...
 
Bon, j'ai fait ça :  
 

Code :
  1. Public Sub RunServer()
  2.   Me.tcpListener.Start()
  3.   Dim mt As New Thread(AddressOf EcouteConstante)
  4.   mt.Start()
  5. End Sub
  6. Public Sub EcouteConstante()
  7.         While True
  8.             Me.CallDisplayMessage("Réception en cours." )
  9.             Me.tcpClient = Me.tcpListener.AcceptTcpClient()
  10.             ' Get the stream
  11.             Dim networkStream As NetworkStream = Me.tcpClient.GetStream()
  12.             ' Read the stream into a byte array
  13.             Dim bytes(Me.tcpClient.ReceiveBufferSize) As Byte
  14.             networkStream.Read(bytes, 0, CInt(Me.tcpClient.ReceiveBufferSize))
  15.             ' Return the data received from the client to the console.
  16.             Dim clientdata As String = Encoding.ASCII.GetString(bytes)
  17.             clientdata = Replace(clientdata, Chr(0), "" )
  18.             clientdata = Replace(clientdata, Chr(10), "" )
  19.             clientdata = Replace(clientdata, Chr(13), "" )
  20.             Me.CallDisplayMessage("Client sent: " & clientdata)
  21.             Dim Reponse() As Byte = GetReponse(clientdata)
  22.             Me.CallDisplayMessage("Host sending: " & Encoding.ASCII.GetString(Reponse))
  23.             Dim sendBytes As [Byte]() = Reponse
  24.             networkStream.Write(sendBytes, 0, sendBytes.Length)
  25.         End While
  26.         Me.tcpClient.Close()
  27. End Sub


 
Le problème, c'est que lorsqu'il fait  
 
Me.tcpClient = Me.tcpListener.AcceptTcpClient()
 
Il arrête temporairement de recevoir....
J'ai développé un client qui envoie des messages successifs (dans un while, donc plutôt rapidement, ce client étant un client de test, dans la réalité, les messages sont quasiment aussi rapides, puis le serveur fera des accès à une BDD, donc bon...).
 
Ce client envoie son premier message, reçoit la réponse, envoie de le deuxième, et là, plus rien, ou erreur disant que la connexion n'existe plus.
 
J'ai pensé à du multithread, c'est à dire créer par exemple 5 ou 6 threads d'écoute, de manière à ce qu'il y en ai au moins un en écoute, mais je ne sais pas si 2 threads peuvent écouter le même port....
 
La je commence à être perdu... :(

n°1599965
BenO
Profil: Chercheur
Posté le 16-08-2007 à 11:56:44  profilanswer
 

J'ai lu en diagonale :O  
je ne vois pas ce qui cloche dans ton code >.<
 
mais "de mémoire", une solution serait:
 
Tu fais un Accept en boucle et tu dispatches vers d'autres
thread pour le traitement (et la fermeture du socketClient ?).
 
edit:
 
http://www.csharpfr.com/infomsg_SO [...] 50683.aspx
 
Il faudrait utiliser un Pool également ^^ bonne chance :O


Message édité par BenO le 16-08-2007 à 11:59:22
n°1600024
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 14:28:08  profilanswer
 

Ouais, ben c'est pas si facile....
Jusqu'à présent j'utilisais la classe TcpClient (une surcouche de la classe Socket).
Pour utiliser ce fameux Poll, faut passer par la classe Socket (comme dans le lien c# que tu m'as laissé).
 
Mais c'est plus chaud du coup, parce que dans leur exemple, ils expliquent pas ou placer les initialisations, les accepts, la boucle, etc...
 
Quelqu'un a plus d'infos ?
(je continue à chercher une solution qui fonctionne avec ce poll, je posterais du code tout à l'heure)

mood
Publicité
Posté le 16-08-2007 à 14:28:08  profilanswer
 

n°1600048
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 14:58:24  profilanswer
 

Bon...
 
La communication fonctionne... mais j'ai toujours le même problème. Je poste ce que j'ai fait.
 
La méthode RunServer() est lancée par le clic sur un bouton du même nom.
 

Code :
  1. Public Sub RunServer()
  2.         Me.CallDisplayMessage("Démarrage de l'écoute sur le port " & _port.ToString & " du serveur " & _serveur.ToString)
  3.         Me.socklistener.Bind(New IPEndPoint(IPAddress.Parse(_serveur), _port))
  4.         Me.socklistener.Listen(10)
  5.         While True
  6.             If Me.socklistener.Poll(1000000, SelectMode.SelectRead) Then
  7.                 Me.sockclient = Me.socklistener.Accept()
  8.                 Dim mt As New Thread(New ThreadStart(AddressOf Accept))
  9.                 mt.Name = "tclient"
  10.                 mt.Start()
  11.             Else
  12.                 Thread.Sleep(100)
  13.             End If
  14.         End While
  15. End Sub


 
La méthode Accept est lancée en boucle par le thread juste au dessus :  
 

Code :
  1. Public Sub Accept()
  2.         Try
  3.             Me.CallDisplayMessage("Réception en cours." )
  4.             Dim bytes(Me.sockclient.ReceiveBufferSize) As Byte
  5.             Me.sockclient.Receive(bytes, bytes.Length, SocketFlags.None)
  6.             Dim clientdata As String = Encoding.ASCII.GetString(bytes)
  7.             clientdata = Replace(clientdata, Chr(0), "" )
  8.             clientdata = Replace(clientdata, Chr(10), "" )
  9.             clientdata = Replace(clientdata, Chr(13), "" )
  10.             Me.CallDisplayMessage("Client sent: " & clientdata)
  11.             Dim Reponse() As Byte = GetReponse(clientdata)
  12.             Me.CallDisplayMessage("Host sending: " & Encoding.ASCII.GetString(Reponse))
  13.             Dim sendBytes As [Byte]() = Reponse
  14.             Me.sockclient.Send(sendBytes, sendBytes.Length, SocketFlags.None)
  15.         Catch ex As Exception
  16.             Me.CallDisplayMessage("Erreur : " & ex.ToString)
  17.         End Try
  18. End Sub


 
DisplayMessage c'est juste un affichage texte dans une rich text box, le tout en asynchrone et GetReponse c'est la fonction qui analyse ce qu'a envoyé le client et qui met en forme la réponse.
 
Le fonctionnement de mon soft est le suivant :  
 
Je démarre le serveur
Je démarre le client
J'envoie un message depuis le client
Le serveur réceptionne le message et répond
Le client reçoit la réponse et automatiquement envoie un nouveau message...
 
Et là, plus rien. Le second message n'est pas entendu par le serveur (j'ai donc toujours le même problème)...
 
Je n'en peux plus... Je vous en supplie... Sortez moi de ce tunnel sombre  [:ruisseau de larmes]

n°1600066
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 16-08-2007 à 15:10:36  profilanswer
 

regarde le source de ce chat, ça pourrait peut etre t'aider :o
http://stephaneey.developpez.com/t [...] t/sockets/

n°1600108
backdafuck​up
Back to da old skool
Posté le 16-08-2007 à 16:25:48  profilanswer
 

Merci Harko.
 
Ca marche toujours pas comme je veux. Voici mon code :  
 

Code :
  1. Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  2.         Me.CallDisplayMessage("Démarrage de l'application Serveur" )
  3.         'Me.tcpListener = New TcpListener(IPAddress.Parse(_serveur), _port)
  4.         Me.socklistener = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
  5. End Sub
  6. Public Sub RunServer()
  7.         Me.CallDisplayMessage("Démarrage de l'écoute sur le port " & _port.ToString & " du serveur " & _serveur.ToString)
  8.         Me.socklistener.Bind(New IPEndPoint(IPAddress.Parse(_serveur), _port))
  9.         Me.socklistener.Listen(10)
  10.         Dim mt As New Thread(New ThreadStart(AddressOf BoucleEcoute))
  11.         mt.Start()
  12. End Sub
  13. Public Sub BoucleEcoute()
  14.         While True
  15.             If Me.socklistener.Poll(1000000, SelectMode.SelectRead) Then
  16.                 Me.CallDisplayMessage("Debut Accept..." )
  17.                 Me.sockclient = Me.socklistener.Accept()
  18.                 Dim mt As New Thread(New ThreadStart(AddressOf Accept))
  19.                 mt.Name = "tclient"
  20.                 mt.Start()
  21.             Else
  22.                 Thread.Sleep(100)
  23.             End If
  24.         End While
  25. End Sub
  26. Public Sub Accept()
  27.         Try
  28.             Me.CallDisplayMessage("Nouveau Thread de réception." )
  29.             Dim bytes(Me.sockclient.ReceiveBufferSize) As Byte
  30.             Me.sockclient.Receive(bytes, bytes.Length, SocketFlags.None)
  31.             Dim clientdata As String = Encoding.ASCII.GetString(bytes)
  32.             clientdata = Replace(clientdata, Chr(0), "" )
  33.             clientdata = Replace(clientdata, Chr(10), "" )
  34.             clientdata = Replace(clientdata, Chr(13), "" )
  35.             Me.CallDisplayMessage("Client sent: " & clientdata)
  36.             Dim Reponse() As Byte = GetReponse(clientdata)
  37.             Me.CallDisplayMessage("Host sending: " & Encoding.ASCII.GetString(Reponse))
  38.             Dim sendBytes As [Byte]() = Reponse
  39.             Me.sockclient.Send(sendBytes, sendBytes.Length, SocketFlags.None)
  40.             Me.sockclient.Disconnect(True)
  41.         Catch ex As Exception
  42.             Me.CallDisplayMessage("Erreur : " & ex.ToString)
  43.         End Try
  44. End Sub


 
Le problème est maintenant le suivant :  
 
Le serveur boucle de façon infinie sur l'accept. Dès qu'il a des données, il les récupère dans un autre thread.
 
Mon client envoie en fait 5 messages d'affilée (via un FOR).
Le premier message est reçu par le serveur, mais les 4 autres sont balancés dans vide. Le fait est que le serveur plante s'il n'y a pas de connexion, donc, il y a une connexion, mais un problème dont je connais pas l'origine....
 
Une idée ?


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C#/.NET managed

  Problème Vb.Net TCP/IP

 

Sujets relatifs
problème avce .jarProblème pour créer une table avec phpmyadmin
[vbs] Problème avec la méthode ReadLineProblème droits d'accès répertoire en C#
Probleme de date pour flux RSSProblème avec la fonction "exec()"
Problème de mise à jour de formulaire[Opengl] Problème d'éclairage
SWING - JAVA Problème avec des sous-panneauxPROBLEME DE DATE LORS DE L'IMPORTATION SOUS EXCEL
Plus de sujets relatifs à : Problème Vb.Net TCP/IP


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR