views:

558

answers:

2

I have to connect via tcp to a server that terminates responses with 0x4 instead of the standard 0x0. I want to keep things simple and use a synchronous send/receive from the socket class. The send works but the receive blocks indefinitely because the server does not terminate messages with 0x0. I cannot synchronously read to the first 0x4 and close because I need to keep the connection open to send more messages. It would be great if I could just read data on a separate thread using BeginReceive but it looks like it still needs the 0x0 terminator. I tried passing a buffer of size 1 to BeginRecieve hoping that it would call my delegate for each char read but it does not seem to work that way. It reads the first char and stops.

Any Ideas?

Here's the 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 
    }
}

}

A: 

Here C# / CSharp Tutorial » Network are many samples about.

lsalamon
+1  A: 

The termination with 0x04 seems dubious, but the reason your code is stopping after one byte, is that you only asked for one byte. If you want a second byte you have to ask again.

Changing your ByteReceived as follows should get you all the bytes up until you hit a 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);
    }
}

The typical way to read an http response is to read bytes until you hit the terminator for the header, then use the content length field in the http header to figure out how many bytes you have left to read.

Again the 0x04 termination seems dubious.

grieve