.NET / Silverlight:DataContractSerializer 字节数组和套接字:意外的 EOF 反序列化

发布于 2024-08-15 22:17:25 字数 2412 浏览 5 评论 0原文

我目前正在使用套接字尝试在 Silverlight 3 客户端和 .NET3.5 服务之间发送消息。我可以很好地设置 TCP 连接并发送数据,但我的问题在于序列化和反序列化 DataContracts。

目前,我们正在使用 WCF PollingDuplex 绑定来完成这项工作,但我们对其性能并不满意,因此正在尝试套接字,同时仍然尝试使用 DataContract 属性。我的代码如下:

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

ReadObject 行抛出 XmlException: Unexpected End of File。我尝试了各种方法,包括在收到字节数组(_recieveBuffer)时截断尾随的 0,在末尾只留下一个 0 等,但似乎没有任何效果。我检查了客户端和服务器端的 byte[] 缓冲区,它们在开头和结尾具有相同的值,并且长度相同。我还尝试使用 actionMessage.GetType() 和 typeof(ActionMessage) 作为 DataContractSerializer 的参数,但没有区别...

我在这里缺少什么:为什么 dataContractSerializer.Write() 不接受 dataContractSerializer 生成的输出。读() ?

我度过了愉快的一天,直到遇到这个...我确实找到了另一个有同样问题的人,但提供的解决方案,在服务端设置 memoryStream.Position = 0 不起作用...

提前致谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘人皮目录ツ 2024-08-22 22:17:25

如果我不得不猜测,我会说你的 memoryStream.Position = 0;线路位置错误。

将缓冲区写入流后,您需要重置流中的位置。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文