Java套接字-如何确定服务器端的数据类型?
我正在使用 Java 套接字作为客户端-服务器应用程序。我遇到一种情况,有时客户端需要发送字节数组(使用 byteArrayOutputStream),有时它应该发送自定义 java 对象。如何从服务器端的输入流中读取信息并确定流中的内容以便我可以正确处理该信息?
I'm using Java sockets for client - server application. I have a situation when sometimes client needs to send a byte array (using byteArrayOutputStream) and sometimes it should send a custom java object. How can I read the information from the input stream on the server side and determine what is in the stream so that I can properly process that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
通常,这是通过在正文前面发送包含有关正文的信息的“标头”来完成的。例如,查看 HTTP 协议。 HTTP 流存在一个标头,该标头与正文之间通过双换行符分隔。标头又包含多个采用
name: value
格式的字段,每个字段均由一个换行符分隔。在这种特殊情况下,您可以在 HTTP 中使用Content-Type
标头来标识正文的数据类型。由于 Java 和 TCP/IP 没有为此提供标准设施,因此您需要详细指定并记录要通过线路发送的格式,以便另一方知道如何处理流。您当然也可以获取标准规格。例如 HTTP 或 FTP。
Usually this is to be done by sending a "header" in front of the body containing information about the body. Have a look at for example the HTTP protocol. The HTTP stream exist of a header which is separated from the body by a double newline. The header in turn exist of several fields in
name: value
format, each separated by a single newline. In this particular case, you would in HTTP have used theContent-Type
header to identify the data type of the body.Since Java and TCP/IP doesn't provide standard facilities for this, you would need to specify and document the format you're going to send over the line in detail so that the other side knows how to handle the stream. You can of course also grab a standard specification. E.g. HTTP or FTP.
有多种方法可以处理这个问题。
一种是对象序列化,它通过 Java 的 Object(In|Out)putStream 来发送。不过,当您知道何时从流中读取对象时,您会遇到一个小问题。
另一种方法是编组和解组 XML。使用更多的流量,但更容易调试和运行。为此,拥有一个详细记录的 XML 模式会有所帮助。这里的一个优点是您可以使用现有的 XML 库。
如果需要,您可以尝试自定义格式,但它最终可能只是一个草率、不那么冗长的 XML 版本。
There are multiple ways to handle this.
One is Object Serialization, which sends it over with Java's Object(In|Out)putStream. You run into a small problem when knowing when to read the object off the stream though.
Another is to marshal and unmarshal XML. Uses a bit more traffic but is easier to debug and get running. It helps to have a well documented XML schema for this. An advantage here is you can use existing XML libraries for it.
You could try a custom format if you wanted, but it would probably end up being just a sloppy, less verbose version of XML.
一般来说,我不认为 Java 中内置了允许您执行此操作的功能。
相反,请考虑在每条消息中发送更多信息,以解释接下来会出现什么类型。
例如,您可以在消息前添加一个整数前缀,这样每次收到消息时,您都会读取前 4 个字节(整数为 4 个字节)并解释其值(例如 1=字节数组,2=自定义 Java 对象) , 3=另一个自定义 Java 对象,...)。
您还可以考虑添加一个包含消息大小的整数,以便您知道当前消息何时结束以及下一条消息何时开始。
In general, I don't believe there is a feature built into Java that allows you to do this.
Instead, consider sending some more information along with each message that explains what type is coming next.
For example, you might prefix your messages with an integer, such that every time you receive a message, you read the first 4 bytes (an integer is 4 bytes) and interpret its value (e.g. 1=byte array, 2=custom Java object, 3=another custom Java object, ...).
You might also consider adding an integer containing the size of the message so that you know when the current message ends and the next message begins.
我会为此被指责为矫枉过正,但除非您确实需要该协议经济实惠,否则您可能会考虑整理数据。我的意思是,如果不查看数据,您通常无法区分字节数组和其他内容之间的区别,因为您可以想象将所有内容表示为字节数组。
您可以非常轻松地使用 JAXB 将数据编组到 XML 或从 XML 编组数据。 JAXB 甚至可以为您将字节数组对象转换为十六进制字符串或 Base64。
I'm going to get called for overkill for this, but unless you seriously need for this protocol to be economical, you might consider marshalling the data. I mean, without peeking at the data, you can't generally tell the difference between something that's a byte array and something that's something else, since you could conceivably represent everything as a byte array.
You can pretty easily use JAXB to marshall the data to and from XML. And JAXB will even turn byte array objects into hex strings or Base64 for you.
首先将数据读入服务器上的字节数组中。编写您自己的解析例程,除了识别字节数组中的内容之外什么也不做。
其次,根据第一步的识别执行完整的对象解析。如果解析需要传递输入流,您始终可以将在第一步中读取的字节数组放入新的 ByteArrayInputStream 实例中。
First read the data into a byte array on the server. Write your own parsing routine to do nothing more than identify what is in the byte array.
Second perform the full object parsing based on the identification from step one. If the parsing requires passing an inputstream, you can always put the byte array you read in step one into a new ByteArrayInputStream instance.
您需要定义一个协议来指示遵循的数据类型。例如,您可以使用字符串或枚举值开始每次传输。服务器将首先读取此内容,然后根据“标头”值读取以下数据。
You need to define a protocol to indicate what type of data follows. For instance, you could start each transfer with a string or enumerated value. The server would first read this, then read the following data based on the 'header' value.
您可以做的就是在发送的任何数据前面添加一个用于确定类型的整数。
这样,您就可以读取前 4 个字节,然后确定它是什么类型的数据。
What you could do, would be to prepend any data you send with an integer that is used to determine the type.
That way, you could read the first 4 bytes, and then determine what type of data it is.
我认为最简单的方法是使用一个对象,其中包含您将发送的数据及其类型信息。然后你可以发送这个对象,根据这个对象的数据类型属性你可以提取数据。
I think the easiest way is to use an object which contains the data that you will send along with its type information. Then you can just send this object and according to this object's data type property you can extract the data.