'Get rid of noise while using recv in C++

I am receiving data following a certain format over a TCP server by serializing them. the class of the object:

class Command {
private:

    char letter;
    int x;
    int y;
    std::string button;

public:
    Command(char _letter, int _x, int _y, std::string _button) {
        letter = _letter;
        x = _x;
        y = _y;
        button = _button;
    }

    Command(std::string serializedCmd)
    {
        
        size_t delimPos = 0;
        std::vector<std::string> parts;
        while ((delimPos = serializedCmd.find(SERIALIZE_DELIM)) != std::string::npos)
        {
            parts.push_back(serializedCmd.substr(0, delimPos));
            serializedCmd.erase(0, delimPos + 1);
        }

        if (parts.empty()) {
            this->letter = '$';
            this->x = -1;
            this->y = -1;
            this->button = "nan";
            return;
        }

        this->letter = (char)atoi(parts.at(0).data());
        this->x = atoi(parts.at(1).data());
        this->y = atoi(parts.at(2).data());
        this->button = parts.at(3);
    }

    Command() {}
    ~Command() {}

    std::string serialize()
    {
        return std::to_string(letter) + SERIALIZE_DELIM + std::to_string(x) + SERIALIZE_DELIM + std::to_string(y) + SERIALIZE_DELIM + button + SERIALIZE_DELIM;
    }

    char getLetter() { return letter; }
    int getX() { return x; }
    int getY() { return y; }
    std::string getButton() { return button; }

    bool isEmpty() {
        return((this->letter == '$') && (this->x == -1) && (this->y == -1) && (this->button == "nan"));
    }

    void printCommand() {
        std::cout << "letter: " << letter << std::endl;
        std::cout << "x     : " << x << std::endl;
        std::cout << "y     : " << y << std::endl;
        std::cout << "button: " << button << std::endl;
        std::cout << "================" << std::endl;
    }

};

The data after being DeSerialized at the clients end follows this format:

||{key}|{x}|{y}|{button}||
Example: ||$|20|40|nan||

The problem is that when using recv to get the data, it seems that I'm picking up some noise around the command.

Example:

Sending:
||$|301|386|nan||
Reciving:
(¿ⁿ8T√|301|386|╠╠↕▼

The command is there although it's crowded with noise for some reason. The code I'm using to receive the data:

char buf[4096];

    Command c;
    std::string commandTemp = "";
    while (true) {
        memset(buf, '\0', 4096);
        const int size = recv(sock, buf, sizeof(buf), 0);

        std::string s(buf,size);
        std::cout << s << std::endl; 


        buf[size] = 0;
        commandTemp = buf;

        if (!commandTemp.empty()) {
            
            try {
                c = Command(commandTemp);   
                exe(c);  //executes command (unrelated)
            }
            catch (const std::exception& err) {
                std::cout << "Couldn't execute!!!!!!!!" << std::endl;
            }
        }
        else {
            std::cout << "Error empty command!\n";
        }
    }

If I am missing any information I will happily provide it. Can someone maybe tell what the problem is?



Solution 1:[1]

You have to loop on the recv till you get the entire message

This may not be the immediate cause of you problem but you will hit it eventually.

TCP is a stream protocol, not a message protocol. All that TCP guarantees is that the bytes you send are received once and in order. But you might send one 100 byte message and receive 20 5 byte messages. You will say "but it works now", true if on the same machine or the messages are small but not true with larger message over a real netwrok so you must do this

char buf[4096];
Command c;
std::string commandTemp = "";
while (true) {

    memset(buf, '\0', 4096);
    int offset = 0;
    int len = ??;
    while(len > 0){
    
      const int size = recv(sock, buf + offset, sizeof(buf) - offset, 0);
      if (size == 0)
          break; // record that we got incomplete message
      offset += size;
      len -= size;
    }  
 ....

Note that you need to know the length in advance too. So either send fixed length message or prepend a fixed size length to each message and read that first

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1