2009-03-09 5 views
0

Je dois me connecter via tcp à un serveur qui termine les réponses avec 0x4 au lieu de la norme 0x0. Je veux garder les choses simples et utiliser un send/receive synchrone de la classe socket. L'envoi fonctionne mais les blocs de réception sont indéfiniment car le serveur ne termine pas les messages avec 0x0. Je ne peux pas lire de manière synchrone au premier 0x4 et fermer parce que je dois garder la connexion ouverte pour envoyer plus de messages. Ce serait génial si je pouvais juste lire les données sur un fil séparé en utilisant BeginReceive mais il semble qu'il a toujours besoin du terminateur 0x0. J'ai essayé de passer un tampon de taille 1 à BeginRecieve en espérant qu'il appelle mon délégué pour chaque lecture de caractères, mais cela ne semble pas fonctionner de cette façon. Il lit le premier caractère et s'arrête.Socket lire les données de manière asynchrone avec terminaison de message spécial

Des idées?

est ici l'application

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Net; 
using System.Net.Sockets; 


namespace SocketTest 
{ 
    public partial class SocketTestForm : Form 
    { 
     Socket socket; 
     byte[] oneChar = new byte[1]; 

     public SocketTestForm() 
     { 
      InitializeComponent(); 
     } 

     private void GetButton_Click(object sender, EventArgs e) 
     { 
      //connect to google 
      IPHostEntry host = Dns.GetHostEntry("google.com"); 
      IPEndPoint ipe = new IPEndPoint(host.AddressList[0], 80); 
      socket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 
      socket.Connect(ipe); 
      if(socket.Connected) 
       Console.WriteLine("Connected"); 

      //write an http get header 

      String request = "GET/HTTP/1.1\r\nHost: google.com\r\nConnection: Close\r\n\r\n"; 

      socket.Send(Encoding.ASCII.GetBytes(request)); 

      //read the response syncronously, the easy way... 
      //but this does not work if the server does not return the 0 byte... 

      //byte[] response = new byte[5000]; 
      //socket.Receive(response, response.Length, SocketFlags.None); 
      //string res = Encoding.ASCII.GetString(response); 
      //Console.WriteLine(res); 

      //read the response async 
      AsyncCallback onreceive = ByteReceived; 
      socket.BeginReceive(oneChar, 0, 1, SocketFlags.None, onreceive, null); 
     } 

     public void ByteReceived(IAsyncResult ar) 
     { 
      string res = Encoding.ASCII.GetString(oneChar); 
      if (res[0] == 0x4) ; //fire some event 
     } 
    } 
} 

Répondre

2

La terminaison avec 0x04 semble douteuse, mais la raison pour laquelle votre code est l'arrêt après un octet, est que vous ne demandé un octet. Si vous voulez un deuxième octet, vous devez demander à nouveau.

Changer votre ByteReceived comme suit devrait vous obtenir tous les octets jusqu'à ce que vous frappez un 0x04:

public void ByteReceived(IAsyncResult ar) 
{ 
    string res = Encoding.ASCII.GetString(oneChar); 
    if (res[0] == 0x4) 
    { 
     //fire some event 
    } 
    else 
    { 
     AsyncCallback onreceive = ByteReceived; 
     socket.BeginReceive(oneChar, 0, 1, SocketFlags.None, onreceive, null); 
    } 
} 

La façon typique de lire une réponse HTTP est de lire des octets jusqu'à ce que vous appuyez sur la terminaison pour l'en-tête, Ensuite, utilisez le champ de longueur de contenu dans l'en-tête http pour savoir combien d'octets il vous reste à lire.

Encore une fois, la terminaison 0x04 semble douteuse.

Questions connexes