我知道如何在C中通过套接字发送文本消息,我知道如何通过套接字发送二进制数据(图像文件)。如何创建包含文本部分和二进制数据的单个消息?例如:
"messageId: 12, messageLength: 34 {image binary data}"
gmol16391#
TCP不知道什么是“文本”或“消息”。它处理的是字节流。如果你有一个字节数组,你可以通过TCP发送它。如果你有多个数组,你可以通过TCP一个接一个地发送它们,结果将与将所有这些数组连接成一个并将它们作为一大块字节发送没有区别。在TCP上发送字节---任何字节---不是问题。问题是从字节流中提取有意义的部分(“消息”)。它与TCP无关,而与你如何根据你的流 * 内容 * ---也就是你的 * 协议 * 定义“消息”有关。你可以通过说“一条消息是一行,以换行符结尾”来定义你的协议,这对于发送没有嵌入换行符的文本消息来说是很好的。它不适用于二进制消息,因为二进制blob很可能有一个嵌入的换行符。你可以这样定义一个消息:“一个消息是一个4字节的量,解释为一个网络顺序的无符号整数,后面跟着很多字节的有效载荷”。这对文本和二进制消息都很好,但对文本来说有点不方便,因为你必须计算和发送每个字符串的长度。你可以说“我的流包含严格交替的文本和二进制消息,文本以换行符结束,二进制以其长度结束”,这也会起作用,尽管你不能连续发送两个文本或两个二进制消息。你可以说“我的流包含两条消息,一条以换行符结尾的文本,然后是一条二进制消息”。没有显式发送长度,流的结尾就是二进制消息的结尾。看,这都在你的协议里。TCP不在乎。它只知道字节。
wgx48brx2#
TLDR:memcpy和一个特殊的分隔符char,用于分隔文本头和二进制数据。分隔符可以很容易地是一个行尾char(\n)
\n
char* CreateMessage(int messageId, size_t messageLength, char* binaryData, /*out*/ size_t* total) { char szHeader[100] = {0}; size_t headerLen = 0; sprintf(szHeader, "messageId: %d, messageLength: %d\n", messageId, messageLength); headerLen = strlen(szHeader); total = headerLen + messageLength; char* data = malloc(total); memcpy(data, header, headerLen); memcpy(data+headerLen, binaryData, messageLength); return data; }
然后当你想发送一些数据时:
size_t total = 0; char* message = CreateMessage(12, 34, binaryData, &total); send(s, message, total, 0); free(message);
或者,如果你使用的是TCP,你也可以使用两个send调用。一个用于头部(带有'\n'字符),另一个用于二进制数据。接收方必须处理消息的分段和碎片。
2条答案
按热度按时间gmol16391#
TCP不知道什么是“文本”或“消息”。它处理的是字节流。如果你有一个字节数组,你可以通过TCP发送它。如果你有多个数组,你可以通过TCP一个接一个地发送它们,结果将与将所有这些数组连接成一个并将它们作为一大块字节发送没有区别。
在TCP上发送字节---任何字节---不是问题。问题是从字节流中提取有意义的部分(“消息”)。它与TCP无关,而与你如何根据你的流 * 内容 * ---也就是你的 * 协议 * 定义“消息”有关。
你可以通过说“一条消息是一行,以换行符结尾”来定义你的协议,这对于发送没有嵌入换行符的文本消息来说是很好的。它不适用于二进制消息,因为二进制blob很可能有一个嵌入的换行符。
你可以这样定义一个消息:“一个消息是一个4字节的量,解释为一个网络顺序的无符号整数,后面跟着很多字节的有效载荷”。这对文本和二进制消息都很好,但对文本来说有点不方便,因为你必须计算和发送每个字符串的长度。
你可以说“我的流包含严格交替的文本和二进制消息,文本以换行符结束,二进制以其长度结束”,这也会起作用,尽管你不能连续发送两个文本或两个二进制消息。
你可以说“我的流包含两条消息,一条以换行符结尾的文本,然后是一条二进制消息”。没有显式发送长度,流的结尾就是二进制消息的结尾。
看,这都在你的协议里。TCP不在乎。它只知道字节。
wgx48brx2#
TLDR:memcpy和一个特殊的分隔符char,用于分隔文本头和二进制数据。分隔符可以很容易地是一个行尾char(
\n
)然后当你想发送一些数据时:
或者,如果你使用的是TCP,你也可以使用两个send调用。一个用于头部(带有'\n'字符),另一个用于二进制数据。接收方必须处理消息的分段和碎片。