当前位置: 首页 > 知识库问答 >
问题:

使用协议缓冲区从Java服务器发送二进制文件到C#Unity3d客户端

田马鲁
2023-03-14

我问过这个问题https://stackoverflow.com/questions/32735189/sending-files-from-java-server-to-unity3d-c-sharp-client但我发现,通过内置操作在Java和C之间发送文件并不是最佳的解决方案,因为我还需要其他消息,而不仅仅是文件内容。

因此,我尝试了使用原型,因为它速度快,并且可以独立于平台序列化/反序列化对象。我的. proto文件如下:

message File{
  optional int32 fileSize = 1;
  optional string fileName = 2;
  optional bytes fileContent = 3;
}

因此,我为生成的中的每个变量设置值。java文件:

file.setFileSize(fileSize);
file.setFileName(fileName);
file.setFileContent(ByteString.copyFrom(fileContent, 0, fileContent.length);

我看过很多关于如何将对象写入文件并从中读取的教程。然而,我找不到任何关于如何将文件从服务器套接字发送到客户端套接字的示例。

我的意图是序列化java服务器上的对象(文件大小、文件名和文件内容)并将这些信息发送到C#客户端。因此,文件可以反序列化并存储在客户端。

在我上面的示例代码中,服务器读取文件(图像文件)的字节并将其写入输出流,以便客户端可以通过输入流将字节读写到磁盘。我想通过序列化我生成的. proto文件来实现同样的事情。

有谁能给我举个例子或给我一个如何做到这一点的提示吗?

共有1个答案

暴阳州
2023-03-14

正如在留档中所述的,协议buf不关心消息在哪里开始和停止,所以当使用TCP之类的流套接字时,您必须自己去做。

从文档:

[...]如果您想将多条消息写入单个文件或流,则由您来跟踪一条消息的结束位置和下一条消息的开始位置。协议缓冲区线格式不是自定义的,因此协议缓冲区解析器无法自行确定消息的结束位置。解决此问题的最简单方法是在编写消息本身之前写入每条消息的大小。当您重新读取消息时,您会读取大小,然后将字节读入单独的缓冲区,然后从该缓冲区进行解析。[...]

长度前缀是一个很好的候选者。根据您编写的语言,有些库可以为例如TCP进行长度前缀,您可以使用,或者您可以自己定义它。

线路上缓冲区的示例表示形式可能是(缓冲区的开头在左侧):

[buf_length|serialized_buffer2]

因此,在发送之前对缓冲区进行打包的代码可能如下所示(这在带有node.js的javascript中):

function pack(message) {
  var packet = new Buffer(message.length + 2);

  packet.writeIntBE(message.length, 0, 2);
  message.copy(packet, 2);

  return packet;
}

要阅读,你必须做相反的事情:

client.on('data', function (data) {
  dataBuffer = Buffer.concat([dataBuffer, data]);

  var dataLen = dataBuffer.readIntBE(0, 2);

  while(dataBuffer.length >= dataLen) {
    // Message length excluding length prefix of 2 bytes
    var msgLen = dataBuffer.readIntBE(0, 2);

    var thisMsg = new Buffer(dataBuffer.slice(2, msgLen + 2));

    //do something with the msg here

    // Remove processed message from buffer
    dataBuffer = dataBuffer.slice(msgLen + 2);
  }
});

您还应该注意,当在TCP套接字上发送多个原型时,它们可能会被缓冲以进行网络优化(连接)并一起发送。这意味着无论如何都需要某种分隔符。

 类似资料:
  • 问题内容: 我正在尝试找到一种方法,将不同文件类型的文件从服务器发送到客户端。 我在服务器上有以下代码将文件放入字节数组: 然后,我将fileData作为字符串发送给客户端。这对于txt文件效果很好,但是当涉及到图像时,我发现尽管它可以很好地创建包含数据的文件,但图像无法打开。 我不确定我是否正在按照正确的方式进行操作。谢谢您的帮助。 问题答案: 如果要读取/写入二进制数据,则应使用字节流(Inp

  • 问题内容: 我正在尝试从服务器向客户端发送文件,即服务器请求的客户端。客户端指定中的文件,然后将其发送到服务器,服务器将文件大小添加到文件中,然后将其返回给客户端。 客户端向其管道添加具有正确文件大小的新文件。 服务器使用上下文和所需文件创建一个新文件,并尝试发送该文件,但是从不读取该字节。 我在这里做错了什么? 记录 客户 FileRequestHandler.java FileChunkReq

  • 我有一个二进制数据缓冲区,我想存储在协议缓冲区中。 在留档(https://developers.google.com/protocol-buffers/docs/proto#scalar)中,它说类型等价于C中的。我无法相信这一点,所以我不得不尝试它,是的,这似乎是这样... 本协议: 给出一个包含以下内容的消息定义: 公共setter/getter API如下所示: 当然,这不是在消息中存储二

  • 我的目标是用扩展名解析协议缓冲区文件。pb。一串在Mac上使用自制软件下载Protobuff。运行protoc--版本,并具有libprotoc 3.1.0版本。 但当我运行Python时,它会说找不到模块。我改变了主意。pb文件名到\u pb2。py并在Python脚本中导入模块。 我正在使用谷歌文档,但仍然没有任何运气。我在编译Protobuf时也遇到了问题。so文件通过Python。我只是无

  • 我正在创建我的产品,并与这个问题。有一天,我设置了Socket.io,一切都很好。第二天,我将服务器和客户端从http迁移到HTTPS。迁移后客户端和服务器端仍然连接,但不能从客户端发射到服务器,从服务器发射到客户端。 我的ssl证书位于和中,它们加载正确。运行在上的服务器 我的示例react组件。我的react应用程序运行在上。HTTPS连接良好,工作良好。 我该怎么办?也许我在中错误地使用了s

  • 我正在制作一个应用程序,将发送1MB长度的数据。Bellow是我的测试代码,它只是发送一个1MB的简单字节数组,然而,即使当我尝试将发送缓冲区增加到1MB或更高时,它也不断抛出Bellow异常。 system.net.sockets.socketexception未处理errorcode=10040 hresult=-2147467259 message=数据报套接字上发送的消息大于内部消息缓冲区