2009-03-09 10 views
0

Ich muss über tcp mit einem Server verbinden, die Antworten mit 0x4 statt der Standard 0x0 beendet. Ich möchte die Dinge einfach halten und ein synchrones Senden/Empfangen von der Socket-Klasse verwenden. Der Sendevorgang funktioniert, aber die Empfangsbausteine ​​bleiben auf unbestimmte Zeit, da der Server Nachrichten mit 0x0 nicht beendet. Ich kann nicht synchron zum ersten 0x4 lesen und schließen, weil ich die Verbindung offen halten muss, um mehr Nachrichten zu senden. Es wäre großartig, wenn ich nur Daten in einem separaten Thread mit BeginReceive lesen könnte, aber es sieht so aus, als ob es immer noch den 0x0-Terminator benötigt. Ich habe versucht, einen Puffer der Größe 1 an BeginRecieve zu übergeben, in der Hoffnung, dass es meinen Delegaten für jede Char lesen würde, aber es scheint nicht so zu funktionieren. Es liest den ersten Buchstaben und stoppt.Socket Lesen von Daten asynchron mit speziellen Nachricht Terminator

Irgendwelche Ideen?

Hier ist die App

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 
     } 
    } 
} 

Antwort

2

Die Kündigung mit 0x04 fragwürdig scheint, aber der Grund, Ihr Code nach einem Byte zu stoppen, ist, dass Sie nur für ein Byte gefragt. Wenn Sie ein zweites Byte wünschen, müssen Sie erneut fragen.

Ändern ByteReceived wie folgt sollten Sie alle Bytes erhalten, bis Sie ein 0x04 getroffen:

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); 
    } 
} 

Die typische Art und Weise eine HTTP-Antwort zu lesen ist Bytes zu lesen, bis Sie den Terminator für den Header getroffen, Verwenden Sie dann das Inhaltslängenfeld im HTTP-Header, um herauszufinden, wie viele Bytes Sie noch lesen können.

Wieder scheint die 0x04-Terminierung zweifelhaft.