views:

401

answers:

1

Hello

I am currently using sockets to try and send messages between a Silverlight 3 client and a .NET3.5 service. I can set up the TCP connection fine, and send data across, but my issue comes with serialising and deserialising DataContracts.

Currently we are using WCF PollingDuplex binding to do this work, but we are not happy with its performance, so are trying sockets, whilst still attempting to make use of DataContract attributes. The code I have is as follows:

// Client
public void Send(ActionMessage actionMessage)
{
        DataContractSerializer dcs =
            new DataContractSerializer(actionMessage.GetType());

        MemoryStream memoryStream = new MemoryStream();

        dcs.WriteObject(memoryStream, actionMessage);

        byte[] sendBuffer = new byte[4096];
        memoryStream.Position = 0;
        memoryStream.Read(sendBuffer, 0, sendBuffer.Length);

        SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();

        socketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length);

        if(!_socket.SendAsync(socketAsyncEventArgs))
            HandleSendComplete(socketAsyncEventArgs);
    }

// Service

private byte[] _recieveBuffer = new byte[4096];
private int _receivedLength;

private void socket_OnReceiveComplete(IAsyncResult asyncResult)
{
        _receivedLength += _tcpClient.Client.EndReceive(asyncResult);

        // See if there's more data that we need to grab
        if (_receivedLength < _recieveBuffer.Length)
        {
            // Need to grab more data so receive remaining data
            _tcpClient.Client.BeginReceive(_recieveBuffer, _receivedLength,
                _recieveBuffer.Length - _receivedLength, SocketFlags.None,
                new AsyncCallback(socket_OnReceiveComplete), null);

            return;
        }

        MemoryStream memoryStream = new MemoryStream();

        memoryStream.Position = 0;
        memoryStream.Write(_recieveBuffer, 0, _recieveBuffer.Length);

        DataContractSerializer dcs = new DataContractSerializer(typeof(ActionMessage));

        object o = dcs.ReadObject(memoryStream);

        ActionMessage actionMessage = (ActionMessage) o;
}

It is the ReadObject line that throws the XmlException: Unexpected End of File. I have tried various things including truncating trailing 0's from the byte array (_recieveBuffer) when it is received, leaving just one 0 at the end etc, but nothing seems to work. I have checked the byte[] buffers on the client and the server side and they have the same values at the beginning and end and are of the same length. I have also tried using actionMessage.GetType() and typeof(ActionMessage) as parameters to the DataContractSerializer, but there is no difference...

What am I misssing here: why does dataContractSerializer.Write() not accept the output generated by dataContractSerializer.Read() ?

I was having a good day until hitting this...I did find one other guy with the same problem, but the solution offered, to set memoryStream.Position = 0 on the service side did not work...

Thanks in advance.

A: 

If I had to guess, I would say that your memoryStream.Position = 0; line is in the wrong place.

You will need to reset position in the stream after writing the buffer into the stream.

Scott P