簡體   English   中英

解析字符串並嘗試查找'\\ 0'字符時出錯

[英]Error with parsing string and trying to find '\0' character

我試圖讓一方將錯誤消息發送給客戶端,但是客戶端無法正確解析它。

我的錯誤是我的parseString函數中的>>>>>,它使index = 0,因此我的'substr'調用超出范圍。

服務器端:::

   #define ERRBUFSIZE 51

    string error = "Error - Already Registered: ";
                error.append(name);
                char err[ERRBUFSIZE];
                err[0] = 0;
                std::copy(error.begin(), error.end(), err+1);

                err[error.size() + 2] = '\0';

                if (send(sock, &err, ERRBUFSIZE, 0) < 0)
                {
                DieWithError("send() failed");
                }

客戶端(正在接收):

   char msgBuffer[ERRBUFSIZE];
        int bytesRcvd = 0;
        int totalRcvd = 0;
        while(totalRcvd != ERRBUFSIZE)
        {   
            // Get Message from Server
            if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

            totalRcvd += bytesRcvd; 
        }

        cout << "Bytes received: " << totalRcvd << endl;
        msgBuffer[totalRcvd] = '\0';

        string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
        cout << rcvMsg << endl;
        rcvMsg = parseString(rcvMsg);

        return rcvMsg;

哪里....

   string TCPClient::parseString(string message)
    {
        cout << "parsing new string" << endl;
        int index = message.find('\0');
        string result = message.substr(0, index);
        cout << "THE RESULT :: " << result << endl;
        return result;
    }

為什么不將您的parseString更改為以下內容:

string TCPClient::parseString(const string& message, int strLength )
{
    cout << "parsing new string" << endl;
    string result = message.substr( 0, strLength );
    cout << "THE RESULT :: " << result << endl;
    return result;
}

然后將調用代碼更改為:

rcvMsg = parseString(rcvMsg, totalRcvd );

否則,您甚至可以使用字符串的“ size()”函數。

編輯:還值得注意的是,查找將通過字符串前進,直到找到'\\ 0'字符,但實際上不會查找它。 將字符串放入字符串對象(存儲長度),然后嘗試通過一個緩慢的迭代過程自己計算長度,這似乎有些奇怪。

Edit2:如果只想使用字符數組,則可以執行以下手動搜索。

int index = 0;
while( *charString++ != '\0' ) index++;

就這么簡單:)

從(非常難於閱讀)代碼來看,我認為您可能會遇到“索引地獄”的問題。

檢查totalRecvd實際上是您要寫入\\0的索引,並在創建rcvMsg時向其中添加\\0索引(當您放置字符串結束標記時, msgBuffer + totalRcvd看起來像狗狗一樣在totalRcvd字節上,通常會在您寫入的(start,end-1)個索引之間得到一個字符串)。

另外-搜索\\0沒有任何意義,因為那只是一個標記。

另外(2)-如果totalRcvd == ERRBUFSIZE您無法訪問msgBuffer [totalRcvd] ,則只能訪問范圍為(0, ERRBUFSIZE -1)的索引

要管理緩沖區時,請使用std :: vector而不是std :: string。 '\\ 0'和std :: basic_string結合不好。

首先,該協議令人討厭。 當您要發送一個以nul結尾的字符串時,您將發送固定大小的塊...將字符串長度放在消息的開頭會更簡單。

其次,您沒有從套接字正確讀取數據,只要管道中沒有其他消息,它就可以正常工作。 如果您的while循環曾經真正行使過,則您將用隨后的所有讀取覆蓋第一個片段。

無論如何,該錯誤的直接原因是您在字符串前添加了nul終止符(分隔符?)。 難道不是在解釋為什么總是在索引0處找到nul嗎? 如果看不到,請嘗試寫出發送時緩沖區的內容。

#define ERRBUFSIZE 51

void server(string const &name)
{
    string error = "Error - Already Registered: ";
    error.append(name);
    char err[ERRBUFSIZE];
    // you sure you want a NUL terminator at index 0??
    err[0] = 0;
    // can replace both lines with strcpy(err, error.c_str())
    std::copy(error.begin(), error.end(), err+1);
    err[error.size() + 2] = '\0';

    if (send(sock, &err, ERRBUFSIZE, 0) < 0)
        DieWithError("send() failed");
}

string parseString(string const &message) // no need to copy
{
    // ... this is redundant anyway, see below
}

string client()
{
    char msgBuffer[ERRBUFSIZE];
    int bytesRcvd = 0;
    int totalRcvd = 0;
    while(totalRcvd != ERRBUFSIZE)
    {       
        // Get Message from Server
        // ... recv(sock, msgBuffer+totalRcvd, ERRBUFSIZE-totalRcvd) ...
        if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

        totalRcvd += bytesRcvd; 
    }

    cout << "Bytes received: " << totalRcvd << endl;
    //sizeof(msgBuffer)==ERRBUFSIZE==totalRcvd, so this overflows
    msgBuffer[totalRcvd] = '\0';

    // assuming you skip the leading \0, msgBuffer is already nul-terminated
    // so use string rcvMsg(msgBuffer) and skip the parseString/substr
    string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
    cout << rcvMsg << endl;
    // rcvMsg = parseString(rcvMsg);

    return rcvMsg;
}

暫無
暫無

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

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