【问题标题】:Send object over a TCP connection通过 TCP 连接发送对象
【发布时间】:2016-02-02 22:58:56
【问题描述】:

我今天开始windows mobile编程,并成功连接到我的服务器。

我在 Visual Studio 上制作的应用程序不是通用应用程序,而是 Windows Mobile 应用程序。

APIDataWriter用于将数据写入输出流,在应用场景中输出流是套接字。即:

            DataWriter dw = new DataWriter(clientSocket.OutputStream);

我一直在研究的一种方法是WriteBytesWriteBuffer (可以通过API documentation for DataWriter找到她的文档 .

我使用哪种方法,为什么? 如何使用上述方法转换此类并将其发送到我的服务器。

    public class Message
    {
       public string pas { get; internal set; }
       public int type { get; internal set; }
       public string us { get; internal set; }#
    }

    //the below code goes in a seperate function 
    DataWriter dw = new DataWriter(clientSocket.OutputStream);
    Message ms = new Message();
    ms.type = 1;
    ms.us = usernameTextBox.Text;
    ms.pas = usernameTextBox.Text;
    //TODO: send ms to the server

【问题讨论】:

    标签: c# tcp windows-mobile windows-networking stream-socket-client


    【解决方案1】:

    在这两种方法之间,WriteBytes() 似乎是更简单的方法。 WriteBuffer() 为您提供对输出缓冲区/流的更多控制,您当然可以在需要时使用。但是,出于所有意图和目的,如果您只需要打开一个连接并向其发送一个字节流,WriteBytes() 就可以完成这项工作。

    如何转换这个类并将其发送到我的服务器

    这完全取决于你,真的。您需要做的是定义您将如何“序列化”您的类以通过连接传输(因此必须在其他代码时“反序列化”它接收数据)。

    a few ways to do that 等等。一种简单的方法(取自该链接问题的最佳答案)是使用 BinaryFormatter 类。像这样的:

    var ms = new Message();
    ms.type = 1;
    ms.us = usernameTextBox.Text;
    ms.pas = usernameTextBox.Text;
    
    byte[] serializedMessage;
    var formatter = new BinaryFormatter();
    using (var stream = new MemoryStream())
    {
        formatter.Serialize(stream, ms);
        serializedMessage = ms.ToArray();
    }
    
    // now serializedMessage is a byte array to be sent
    

    然后在另一端,您需要将其反序列化回对象实例。可能看起来像这样:

    // assuming you have a variable called serializedMessage as the byte array received
    
    Message ms;
    using (var stream = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        stream.Write(serializedMessage, 0, serializedMessage.Length);
        stream.Seek(0, SeekOrigin.Begin);
        ms = (Message)formatter.Deserialize(stream);
    }
    

    您当然可以在更简单的界面后面抽象出这些。或者,如果您正在寻找序列化中的任何人类可读性,您可以尝试使用 JSON 序列化程序并将字符串直接转换为字节数组等。


    编辑:请注意,这实际上只是“序列化”对象的众多方法之一的示例。而且,正如下面 cmets 中的一位用户所指出的,使用此二进制序列化程序可能存在缺陷。

    可以使用任何序列化程序,真的。你甚至可以自己制作。从技术上讲,覆盖.ToString() 以打印所有属性,然后调用这是一种序列化形式。这个概念总是一样的......将内存中的对象转换为可传输的数据,以后可以从中构建相同的内存中对象。 (从技术上讲,保存到数据库是一种序列化形式。)

    【讨论】:

    • 感谢您的快速回答。 Windows Phone 似乎使用了提供DataContractJsonSerializer 的 JSON API。所以我使用了 WriteObject(stream,ms) 。这样做我使用ms.ToArray() 方法来存储字节。但是在服务器端,这是一个 Windows 控制台应用程序,我得到了附加信息:二进制流“0”不包含有效的 BinaryHeader。可能的原因是无效的流或序列化和反序列化之间的对象版本更改。 ` ms = (Message)formatter.Deserialize(stream);`
    • @Moynul:对象是否按预期序列化并通过连接发送?服务器接收到的流是否与客户端发送的流长度相同?听起来这里需要做一些直接的调试,很遗憾我不能为你做。 (您使用的反序列化方法与用于序列化的 相同 方法对吗?这部分很重要。)
    • 请原谅我的幼稚/缺乏知识,因为我对套接字编程还是新手。从客户端的调试来看,serializedMessage 似乎为空。所以我使用DataContractJsonSerializer 实现的序列化失败了。在服务器端 serializedMessage = new byte[client.ReceiveBufferSize]; 在调试输出中返回 null。
    • @David 我建议不要将BinaryFormatter 用于在机器之间保留或传输的任何数据。 BinaryFormatter 非常不容忍序列化和反序列化之间的程序集版本号差异。只是在两侧有不同数量的 Windows 更新可能会导致它失败。我建议使用几乎任何其他序列化程序。我唯一推荐使用BinaryFormatter 的方法是用于同一台机器上的非持久IPC(对于特定的用例,它工作得很好)。
    • @Moynul:在这种情况下,您需要首先关注客户端。如果它为空,则服务器没有从它接收任何数据。您还可以尝试使用不同的 JSON 序列化程序,例如 JSON.NET(Newtonsoft 提供),它可以作为 NuGet 包轻松获得。它可以轻松地在字符串之间进行序列化非常,并且字符串和字节数组之间的转换非常简单(只需确保在客户端和服务器上使用相同的字符编码)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    相关资源
    最近更新 更多