3

请原谅我的 C#.Net 新手状态。如果这很明显并且我从文档中错过了它,将不胜感激提供相关页面或示例代码的链接。

我正在开发一个将接受来自 Java 应用程序的 TCP 套接字连接的应用程序。(是的,那部分需要 Java。它是 Sun SPOT 设备,Java 是唯一的选择。)Java 应用程序将定期将新数据写入套接字,我的应用程序的工作是接收字节 [],转换将其转换为字符串,处理数据(更新 UI 等),并可能将数据转发到另一台运行类似 C#.NET 应用程序的计算机上。

以下是我到目前为止所做的: 现在,应用程序在启动时启动了一个线程,该线程打开了一个套接字。Java 应用程序可以成功连接到套接字,以便正常工作。我正在查看 NetworkStream 的beginRead方法和dataAvailable, length, 和CanRead属性,但我不完全确定如何确定何时读取了一个数据包,通常约为 512 个字节,但可能会有所不同。

如果 Java 应用程序将数据写入流或有数据积压(Java 应用程序将很快传递数据。)如何确保一次只读取一个数据包?如果 Java 应用程序 null 在写入时终止数据,那会有帮助吗?够了吗?

最后,套接字只会接收一个连接,但我需要让它保持打开状态,直到出现错误或连接终止。处理这方面的最优雅的方式是什么?由于在 Sun SPOT 基站上运行的 Java 应用程序的快速启动(近乎实时)方面,我认为关闭并重新打开每个数据包都不会起作用。现在,当基站终止时,我的应用程序会大声而痛苦地死去。:)

感谢您的阅读以及您可以提供的任何帮助。

4

3 回答 3

5

“如果 Java 应用程序将数据写入流或有数据积压(Java 应用程序将很快传递数据。)我如何确保一次只读取一个数据包?”

请注意不要假设您可以控制哪些数据最终会出现在哪个数据包中。如果您尝试发送字节数据{ 'H', 'e', 'l', 'l', 'o' },则无法保证所有这些数据都将在单个数据包中发送。虽然极不可能,但每个数据包仍可能仅包含一个字节,因此您将在 5 个不同的事件中收到所有五个字节。关键是,不要以这种方式依赖数据包。相反,定义您自己的消息结束终止符,并将所有传入数据简单地放入某种字节缓冲区中,并使用另一个函数来检测是否存在这些终止符中的任何一个。如果是这样,请阅读该终结者。例如,假设您从 Java 应用程序调用相应的 send 方法两次,其中包含以下数据:

{ 'H', 'e', 'l', 'l', 'o', '\0' }
{ 'W', 'o', 'r', 'l', 'd', '\0' }

你的应用程序应该如何准备接收数据应该是这样的:

Server receives { 'H', 'e', 'l' }
Data stored in byte buffer { 'H', 'e', 'l' }
Check byte buffer for message terminator '\0'. None found. Buffer unchanged, no message processed.
Server receives { 'l', 'o', '\0', 'W' }
Data stored in byte buffer { 'H', 'e', 'l', 'l', 'o', '\0', 'W' }
Check byte buffer for message terminator '\0'. 1 found, extracted message { 'H', 'e', 'l', 'l', 'o' } and buffer updated { 'W' }

因此,虽然这并不完全是对您最初问题的回答,但我认为它应该可以推动您朝着正确的方向前进。

您可能会遇到的一件事是,根本没有任何字符不能成为数据而不是消息终止符。例如,许多文件包含数据 \0,因此这些文件会破坏您的消息检测。通常如何处理这个问题是通过为您的协议创建一个标头规范并检测您是否期望一个标头(在这种情况下,查找 \0 将表示消息的结尾)或者您是否正在等待一定数量的数据(可以由收到的最后一个标头指定。)如果这没有意义,并且您认为您可能需要使用此技术,请告诉我,我将添加到此答案中。

于 2009-01-17T20:20:27.447 回答
1

当您读取流数据时,您需要一些标记/终止字符或已知大小的数据来确定何时停止读取和处理信息。空字符或换行符很常见。另一种技术是使用固定大小的标头来指定正文的长度。

套接字将保持打开状态,直到您将其关闭或另一端终止,在这种情况下,您将在从您应该处理的套接字读取时收到错误。当在读取或写入操作期间从远程端关闭套接字时,NetworkStream 会引发 IOException。

于 2009-01-17T17:43:47.420 回答
0

我们解决这个问题的方法是结合使用标记字符和固定宽度字段。前两个字节是整个数据包的长度标头。然后,我将数据包读入 byte[] 缓冲区,然后依靠我们自己的数据包结构来知道,例如,前两个字节分别被解释为单独的字段,然后字符串字段以 \n 字符终止(如果您在家得分,则为 0x0A)。然后,通过读取 8 个连续字节等来处理长数据字段。这对我们来说似乎工作得很好,但这显然是一种解决方案,即一个人可以控制套接字的两端,而不是只有一个能够控制一端。希望这对其他人也有帮助。

于 2009-02-16T15:27:23.527 回答