通过 TCP 套接字发送大型 base64 字符串

Sending Large Base64 String over TCP Socket

本文关键字:大型 base64 字符串 TCP 套接字 通过      更新时间:2023-10-16

我正在尝试使用 GO 和 TCP 服务器从 TCP 客户端发送 Base64 编码的图像 C++.

这是C++接收器的代码片段

std::string recieve(int bufferSize=1024,const char *eom_flag = "<EOF>"){
char buffer[bufferSize];
std::string output;
int iResult;
char *eom;
do{
iResult = recv(client, buffer, sizeof(buffer), 0);
//If End OF MESSAGE flag is found.
eom = strstr(buffer,eom_flag);
//If socket is waiting , do dot append the json, keep on waiting.
if(iResult == 0){
continue;
}
output+=buffer;
//Erase null character, if exist.
output.erase(std::find(output.begin(), output.end(), ''), output.end());
//is socket connection is broken or end of message is reached.
}while(iResult > -1 and eom == NULL);
//Trim <EOF>
std::size_t eom_pos = output.rfind(eom_flag);
return output.substr(0,eom_pos);}

想法是接收消息直到找到消息结束,然后继续侦听同一TCP连接上的另一条消息。

Golang TCP 客户端代码片段。

//Making connection
connection, _ := net.Dial("tcp", "localhost"+":"+PortNumber)
if _, err := fmt.Fprintf(connection, B64img+"<EOF>"); err != nil {
log.Println(err)
panic(err)
}

尝试过的方法:

  • 增加C++接收器中的缓冲区大小。
  • 从C++接收器中的字符串末尾删除空字符。

观察:

  • 客户端发送的字符串长度是固定的,而接收函数后的字符串长度较大且 随机。示例:Go 客户端字符串长度为 25243。对于相同的字符串,接收后的长度当 i 循环中的运行发送和接收是 25243、26743、53092、41389、42849。

  • 在将收到的字符串保存在文件中时,我在字符串中看到<0x7f> <0x02>字符。

我正在使用winsock2.h作为c ++套接字。

您将接收到的数据视为 C 字符串 - 以 0 字节结尾的字节序列 - 这是不正确的。

recv接收一些字节并将它们放在buffer中。假设它收到了 200 个字节。

然后你做strstr(buffer,eom_flag);.strstr不知道收到了 200 个字节。strstr从缓冲区的开头开始,并一直查找,直到找到 或 0 字节。它有可能在缓冲区的其他 824 个字节中找到 a,即使您没有收到一个。

然后你做output += buffer;.这也将缓冲区视为以 0 字节结尾。这将查看整个缓冲区(而不仅仅是前 200 个字节(以查找 0 字节。然后,它会将到该点的所有内容添加到output中。同样,它可能会在缓冲区的最后 824 个字节中找到 0 字节,并添加太多数据。它可能根本不会在缓冲区中找到 0 字节,然后它将继续从内存中存储在buffer旁边的其他变量中添加额外的数据。或者它可能会在前 200 个字节中找到一个 0 字节,然后停止到此(但前提是您发送了一个 0 字节(。


您应该做的是注意接收的字节数(iResult(,并将该字节数添加到输出中。您可以使用:

output.insert(output.end(), buffer, buffer+iResult);

另外(正如Phillipe Thomassigny在评论中指出的那样(,"可能不会一次全部收到。您可能会单独收到"。您应该检查output是否有",而不是检查buffer是否有"。(这其中的性能影响留给读者练习(


顺便说一下,这条线目前没有任何作用:

output.erase(std::find(output.begin(), output.end(), ''), output.end());

因为 '\0' 永远不会被添加到output中,因为有了output += buffer;,一个 '\0' 告诉它在哪里停止添加。