C#将对象转换为字节数组
Posted
技术标签:
【中文标题】C#将对象转换为字节数组【英文标题】:C# Converting object to byte array 【发布时间】:2021-11-30 22:01:42 【问题描述】:我正在用 tcp 制作一个聊天系统的东西,它需要以字节数组的形式发送东西,但是当我将图像转换为字节数组时,发送它然后再转换回来它会给出这个错误:“之前遇到的流结束解析完成。'。使用字符串就可以了。
public byte[] ObjectToByteArray(object obj)
BinaryFormatter formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
formatter.Serialize(stream, obj);
return stream.ToArray();
public object ByteArrayToObject(byte[] bytes)
using (var stream = new MemoryStream())
var binForm = new BinaryFormatter();
stream.Write(bytes, 0, bytes.Length);
stream.Position = 0;
var obj = binForm.Deserialize(stream);
return obj;
【问题讨论】:
发送数据时,连接的接收方总是需要知道数据的结束位置。因此,您可以发送固定长度的消息,使用终止符(不是消息的一部分)终止消息,或者在每条消息之前加上一个字节数。传输协议通常有两层 1) 应用层 2) 传输层。您的代码只有一层。您的大脑可以找出每条消息的结束位置的聊天应用程序。一个应用程序,你必须在代码中添加你的大脑所做的事情。 【参考方案1】:这里有两个不同的东西;首先,我怎么强调都不够;不要使用BinaryFormatter
。曾经。它会伤害你。存在许多序列化程序,BinaryFormatter
(以及表亲NetDataContractSerializer
)实际上是您应该使用的绝对最后。如果您愿意,我可以对此进行扩展,或者如果您愿意,我可以提出替代方案。
现在;至于实际问题:我强烈怀疑这不是您认为的那样。基于几十年的网络代码工作,我有一种预感,这里的真正问题是“框架”。我的意思是:TCP 是流协议,而不是消息/数据包协议。我强烈怀疑您没有正确解构发送的确切字节。如果没有看到你的套接字代码,我不能肯定地说这个,但是......正如我所说:这是基于大量经验的预感。要对此进行调查:记下您发送的字节的长度,并记下您收到的字节的长度。我很确定你会发现它们是不同的。如果仍有疑问:获取发送的有效载荷和接收的有效载荷的 base-64 或十六进制字符串(例如Convert.ToBase64String
),并比较该字符串。我很确定它们会变得不同。
最终,网络代码是困难的;我可以尝试解释个别观点,但“如何通过网络正确发送消息”可能会写满一本书。 IMO,如果您对未来 5 年专门编写网络代码不感兴趣:请使用可以为您完成这项工作的现有工具,例如 gRPC。存在大量其他消息传递 RPC 工具。
【讨论】:
我尝试了 Convert.ToBase64String 函数,但这只是返回一个字符串,我需要发送一个对象。我能找到的唯一可以做到这一点的是 BinaryFormatter 我知道它不是很好。我也真的不想使用外部 dll,这在我看来太复杂了。另外,我在服务器端和客户端都使用了问题中的功能,以防您想知道 @GHOST 你误会我了;我提到Convert.ToBase64String
只是为了检查您是否收到了与您发送的完全相同的字节,因为比较字符串非常容易,即使在文本编辑器中也可以通过眼睛进行比较。我的意图不是要替换您现有的序列化。重新编写问题中的代码:除非我能看到您是如何编写和阅读 byte[]
网络的 - 那么该代码(我同意它本身应该可以工作)并不能告诉我太多。
@GHOST re 外部 dll 使事情复杂化......嗯,这是非常主观的;我听到你在说什么,虽然我个人不确定添加 NuGet 包引用是多么不方便(因为其他一切都可以正常工作),但是:这取决于你。我只能说:you have been warned(请注意“我提出我的论文”链接中的真实细节)
是的,在序列化包含对象的类之前,我确实有过这样的经历,但它确实需要一个 dll。我希望 exe 可以作为 exe 轻松发送,这也是我不想要任何 dll 的众多原因之一。我也尝试过 ILMerge 将 dll 合并到 exe 文件中,但也失败了
@GHOST 听起来你实际上想要的是“单文件部署” - 请参阅docs.microsoft.com/en-us/dotnet/core/deploying/single-file - 那么如何组合该功能就不是你的问题了跨度>
以上是关于C#将对象转换为字节数组的主要内容,如果未能解决你的问题,请参考以下文章