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

时间:2019-10-21 14:34:19

标签: c++ sockets go tcp base64

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

这是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(), '\0'), 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 ++接收器中从字符串的末尾删除空字符。

观察:

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

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

我正在将winsock2.h用于c ++套接字。

1 个答案:

答案 0 :(得分:2)

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

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

然后您执行strstr(buffer,eom_flag);strstr不知道收到了200个字节。 strstr从缓冲区的开头开始,一直寻找直到找到或0字节为止。即使您没有收到一个,它也有可能在缓冲区的其他824字节中找到一个。

然后您执行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(), '\0'), output.end());

因为永远不会将'\ 0'添加到output,因为对于output += buffer;,'\ 0'告诉它停止添加的位置。

相关问题