簡體   English   中英

通過 TCP 套接字發送大 Base64 字符串

[英]Sending Large Base64 String over TCP Socket

I am trying to send a Base64 encoded image from TCP client using GO and TCP server in 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(), '\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++ 接收器的字符串末尾刪除 null 字符。

觀察:

  • 客戶端發送的字符串長度是固定的,而收到 function 后的字符串長度較大且隨機。 示例:Go 客戶端字符串長度為 25243。對於相同的字符串,當我在循環中運行發送和接收時,接收后的長度為 25243、26743、53092、41389、42849。

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

我將 winsock2.h 用於 c++ 插座。

您將接收到的數據視為 C 字符串 - 以 0 字節結尾的字節序列 - 這是不正確的。

recv接收一些字節並將它們放入buffer中。 假設它收到了 200 個字節。

然后你做strstr(buffer,eom_flag); . strstr不知道收到了 200 個字節。 strstr從緩沖區的開頭開始,一直查找,直到找到一個或一個 0 字節。 即使您沒有收到一個,它也有可能在緩沖區的其他 824 個字節中找到一個。

然后你做output += buffer; . 這也將緩沖區視為以 0 字節結尾。 這將查看整個緩沖區(不僅僅是前 200 個字節)以找到一個 0 字節。 然后它將到該點的所有內容添加到output中。 同樣,它可能會在緩沖區的最后 824 個字節中找到一個 0 字節,並添加太多數據。 它可能在緩沖區中根本找不到 0 字節,然后它將繼續從存儲在 memory 中buffer旁邊的其他變量中添加額外數據。 或者它可能會在前 200 個字節中找到一個 0 字節,然后停在那里(但前提是您發送了一個 0 字節)。


您應該注意接收到的字節數(即iResult )並將那么多字節添加到 output。 你可以使用:

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' 告訴它在哪里停止添加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM