监视套接字以获取新数据然后处理该数据的最佳方法是什么?

时间:2009-01-17 17:06:28

标签: c# multithreading .net-3.5 sockets sunspot

请原谅我的C#.Net新手状态。如果这是显而易见的并且我从文档中错过了它,那么我们将非常感谢相关页面或示例代码的链接。

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

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

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

最后,套接字只接收一个连接,但我需要保持打开,直到出现错误或连接终止。处理这方面最优雅的方法是什么?我不认为关闭并重新打开每个数据包将起作用,因为在Sun SPOT基站上运行的Java应用程序的快速火灾(几乎实时)方面。现在,当基站终止时,我的应用程序死了一个响亮而痛苦的死亡。 :)

感谢您阅读并提供任何帮助。

3 个答案:

答案 0 :(得分:5)

“如果Java应用程序将数据写入流或存在积压的数据(Java应用程序将相当快速地传递数据。)如何确保我一次只读取一个数据包? “

小心不要假设您可以控制哪些数据在哪个数据包中结束。如果您尝试发送字节数据{ 'H', 'e', 'l', 'l', 'o' },则无法保证所有这些数据都将在单个数据包中发送。尽管极不可能每个数据包仍然可能只包含一个字节,因此您将在5个不同的事件中接收所有五个字节。关键是,不要以这种方式依赖数据包。相反,定义您自己的End Of Message终结符,并简单地将所有传入数据抛入某种字节缓冲区,并检测是否存在任何这些终结符。如果是这样,请阅读该终结器。例如,您可以从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将表示消息的结尾)或者您是否正在等待一定数量的数据(可以通过收到的最后一个标题指定。)如果这没有意义,你认为你可能需要使用这种技术让我知道,我会添加这个答案。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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