I am trying to understand how I would implement message framing with WCF. The goal is to create a server in WCF that can handle proprietary formats over Tcp. I can't use the net.Tcp binding because that is only for SOAP.
I need to write a custom channel that would receive messages in the following format . An example message would be "5 abcde". In particular I am not sure how to do framing in my custom channel.
Here is some sample code
class CustomChannel: IDuplexSessionChannel
{
private class PendingRead
{
public NetworkStream Stream = null;
public byte[] Buffer = null;
public bool IsReading = false;
}
private CommunicationState state = CommunicationState.Closed;
private TcpClient tcpClient = null;
private MessageEncoder encoder = null;
private BufferManager bufferManager = null;
private TransportBindingElement bindingElement = null;
private Uri uri = null;
private PendingRead pendingRead;
public CustomChannel(Uri uri, TransportBindingElement bindingElement, MessageEncoderFactory encoderFactory, BufferManager bufferManager, TcpClient tcpClient)
{
this.uri = uri;
this.bindingElement = bindingElement;
this.tcpClient = tcpClient;
this.bufferManager = bufferManager;
state = CommunicationState.Created;
}
public IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
{
if (this.state != CommunicationState.Opened) return null;
byte[] buffer = bufferManager.TakeBuffer(tcpClient.Available);
NetworkStream stream = tcpClient.GetStream();
pendingRead = new PendingRead { Stream = stream, Buffer = buffer, IsReading = true };
IAsyncResult result = stream.BeginRead(buffer, 0, buffer.Length, callback, state);
return result;
}
public bool EndTryReceive(IAsyncResult result, out Message message)
{
int byteCount = tcpClient.Client.EndReceive(result);
string content = Encoding.ASCII.GetString(pendingRead.buffer)
// framing logic here
Message.CreateMessage( ... )
}
}
So basically the first time around EndTryReceive could just get a piece of the message from the pending read buffer "5 ab". Then the second time around it could get the rest of the message. The problem is when EndTryReceive gets called the first time, I am forced to create a Message object, this means that there will be a partial Message going up the channel stack.
What I really want to do is to make sure that I have my full message "5 abcde" in the buffer, so that when I construct the message in EndTryReceive it is a full message.
Does anyone have any examples of how they are doing custom framing with WCF?
Thanks, Vadim