通过TCP填充数据

问题描述:

我正在开发一个客户端 - 服务器项目,并且需要实现一个逻辑,我需要通过TCP套接字连接检查是否收到最后一个数据,然后才能继续。 为了确保我收到了所有的数据,我计划在发送的最后一个数据包中加上一个标志。我在下面有两个选项,还有相关的概率。通过TCP填充数据

i。如下所示使用一个结构体,并为最后发送的数据包填充vst_pad,并在recv端检查它是否存在。在方案二的优势在于,我没有删除从实际数据中的标志将其写入到file.Just之前检查结构

typedef struct 
    { 
    /* String holding padding for last packet when socket is changed */ 
    char vst_pad[10]; 
    /* Pointer to data being transmitted */ 
    char *vst_data; 
    //unsigned char vst_data[1]; 
    } st_packetData; 

问题是我必须序列的结构上的第一个成员每次发送呼叫。此外,我不确定是否会在一次recv调用中通过TCP接收整个结构,因此每次都必须添加逻辑/开销以检查它。到目前为止,我已经实现了这一点,但后来发现基于流的TCP可能无法保证在一次调用中收回整个结构体。

ii。使用像strncat这样的函数将该标志添加到最后发送的数据。

问题是我必须检查每个接收调用或者使用正则表达式函数或像strstr函数那样的标志的存在,如果必须从数据中删除它。

此应用程序将用于大数据传输,因此希望在每次发送/接收/读取/写入呼叫时增加最小开销。真的很感激知道是否有更好的选择,然后上述两个或任何其他选项来检查收到的最后一个数据包。该程序是多线程的。

编辑:我不知道我要发送的文件的总大小,但我发送的是固定数量的数据。这是fgets读取,直到大小指定为-1或直到遇到新行。

您是否事先知道数据的大小,是否需要实现消息标志的结束?

因为我会简化设计,所以添加一个4字节的标题(假设您不会发送每条消息超过4GB的数据),其中包含消息的预期大小。

因此,您解析出前4个字节,计算大小,然后继续调用recv,直到获得大量数据。

您需要处理recv调用从下一条消息中获取数据的情况,以及显然的错误处理。

如果实际消息包含10个零字节,则会发生如下问题:10字节小键盘解决方案没有提出什么问题 - 假设您用零填充它?你需要避开10字节的零,否则你可能会错误地截断消息。

使用固定大小的标题和已知大小的值将缓解此问题。

+0

Alan:我不知道我要发送的文件的总大小,但是我发送的是固定数量的数据。也就是说,fgets会读取,直到大小指定为-1或直到遇到新行。我可以在缓冲区上使用strlen来查找实际的数据长度。 – user369823 2012-02-27 01:16:24

+1

,当然你必须解析这4个字节,这些字节可能会在4个不同的recv呼叫中到达。 – bew 2012-02-27 16:08:12

+0

@Alan:Thnx为答复到目前为止。我部分实现了你的建议,但我想知道我到底知道了些什么大小要放在标题中。我正在使用fgets读取文件中的数据,并传输相同数量的大小。但是作为它的TCP,我不确定发送数据的大小,直到检查发送呼叫的返回值为止。我有点困惑于此。一个伪代码将是非常有用的... – user369823 2012-06-03 03:10:00

您可以使用用C#编写的开源网络通信库吗?如果是这样结账networkComms.net

+0

问题标记为C,它是一个低级别的TCP消息应用程序。 – Alan 2012-02-26 19:02:34

+0

MarcF:谢谢你的回复。正如Alan所指出的那样,我再次在C.Thnks编码。 – user369823 2012-02-27 02:07:08

对于一条消息(数据包)首先发送一个短的(按网络顺序)的大小,然后是数据。这可以在一个write系统调用中实现。

在接收端,只需read短期和转换回主机顺序(这将使一个在稍后的状态下使用不同的处理器。然后,您可以read数据的其余部分。

+0

埃德:感谢您的答复。我已经发送了固定数量的数据,但不确定从文件中获取的数据是否具有相同的大小或小于它的大小。 fgets和send函数在其调用中具有相同数量的len。你是否建议使用像strlen这样的函数来找出要分配给短变量的实际数据长度? – user369823 2012-02-27 02:04:36

如果这是真正地由你的应用程序发送的最后一个数据在发送端使用shutdown(socket, SHUT_WR);

这将设置TCP标志,它表示发送者 - 接收者流已经结束,接收者将知道这是因为他的recv()在接收到所有内容时将返回0(就像EOF条件),接收器仍然可以发送数据,发送者可以ñ仍然听他们,但它不能发送更多使用此连接。

+0

BatchyX。按照设计我以后会需要相同的连接。我不知道稍后会不会使用相同的连接。这取决于用户的选择。 – user369823 2012-02-27 02:05:52

在这种情况下,通常会将数据分块为块,并提供块头和尾部。标题包含块中数据的长度,所以对等方知道预期的时间 ​​- 只需要计算rx个字节,然后检查一个有效的预告片。该块允许在两端没有大量缓冲区的情况下进行大量数据传输。

在头文件中添加一个可以识别最后一个块的“状态”字节并不麻烦。

另一种方法是打开另一个数据连接,对整个序列化进行流式处理,然后关闭这个数据连接(就像FTP一样)。

+0

Martin:感谢您的及时答复。我可以根据Ed先生在结构中所建议的添加空格来指示数据的长度,然后在recv端循环,直到收到数据量。我会尝试首先执行相同的操作。 – user369823 2012-02-27 02:00:44