我正在开发一个客户端 - 服务器项目,需要实现一个逻辑,我需要在继续之前检查是否通过TCP套接字连接收到了最后一个数据。 为了确保我已收到所有数据,我打算在发送的最后一个数据包上填写一个标志。我有两个选项,如下所示,还有相关的概率。
我。使用如下结构并填充vst_pad以获取最后发送的数据包,并在recv端检查其是否存在。优于选项2的优点是,在将其写入文件之前,我不必从实际数据中删除该标志。只需检查结构的第一个成员
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或直到遇到新行。
答案 0 :(得分:2)
您是否事先知道数据的大小,是否要求您实现消息结束标志?
因为我会简化设计,所以添加一个4字节的标头(假设你没有为每条消息发送超过4GB的数据),它包含了预期的消息大小。
因此,您解析前4个字节,计算大小,然后继续调用recv,直到获得那么多数据。
你需要处理你的recv调用从下一条消息中获取数据的情况,以及明显的错误处理。
如果实际消息包含10个零字节,假设您用零填充它,那么10byte pad解决方案没有提出的另一个问题是什么?你需要逃避10字节的零,否则你可能会错误地截断消息。
使用固定大小的标头和已知的大小值可以缓解此问题。
答案 1 :(得分:1)
对于消息(数据包),首先发送大小的短(网络顺序),然后发送数据。这可以通过一次write
系统调用来实现。
在接收端,只需read
短路并转换回主机顺序(这将使人们可以在以后使用不同的处理器。然后您可以read
其余数据。
答案 2 :(得分:1)
在这种情况下,通常会将数据阻塞为块并提供块头和预告片。标头包含块中数据的长度,因此对等体知道预期何时播放 - 它所要做的就是计算rx字节,然后检查有效的预告片。这些块允许大数据传输,两端都没有大量缓冲区。
在标题中添加一个可识别最后一个块的'status'字节并不是一件容易的事。
另一种方法是打开另一个数据连接,流式传输整个序列化,然后关闭此数据连接(就像FTP一样)。
答案 3 :(得分:0)
您能否使用用C#编写的开源网络通信库?如果是,请结帐networkComms.net。
答案 4 :(得分:0)
如果这确实是您的应用程序发送的最后一个数据,请在发件人方使用shutdown(socket, SHUT_WR);
。
这将设置FIN
TCP标志,表示发送方 - >接收方流已结束。接收器将知道这一点,因为他的recv()将在收到所有内容时返回0(就像EOF条件一样)。接收方仍然可以在之后发送数据,发送方仍然可以监听它们,但是使用此连接无法发送更多数据。