Clearing buffer while reading in binary data from a server in C++

fread
c++ read binary file into buffer
c read binary file byte by byte
c read binary file into buffer
c++ read binary file byte by byte
c++ read binary file into vector
c++ read binary file into string
ifstream read

I have a server that sends raw binary data to print a "map" that a user must traverse through, however, I am having trouble clearing out my buffer after each line read and thus keep getting residual data printed at the end of the shorter lines. In the screenshot below you can see my output on the left, and what the output should be on the right. What is the best way to solve this? I feel like I am missing something but cant seem to find a solution.

And the code that is reading/printing this is below:

char* mapData = NULL;
string command = "command> ";
size_t dataSize = 0;
while(mapData != command.c_str()) {
    unsigned char* buffer = (unsigned char*) &dataSize;
    connection = read(mySocket, buffer, 8);
    if(connection == -1 || connection < 0) {
        cerr << "**Error: could not read text size" << endl;
        return 1;
    }

    mapData = (char*)malloc(dataSize);
    buffer = (unsigned char*) mapData;

    while((connection = read(mySocket, buffer, dataSize)) != -1) {
        if(connection == -1 || connection < 0) {
            cerr << "**Error: could not read text size" << endl;
        return 1;
        }
        if(dataSize != 1) {
            cout << buffer;
        }
        free(buffer);
        buffer = NULL;
    }

}

You are ignoring the return value of read() to know how many bytes are in the buffer.

read() returns the actual number of bytes that were read, which may be fewer than you requested. So you need to call read() in a loop until you have read all of the bytes you are expecting, eg:

int readAll(int sock, void *buffer, size_t buflen)
{
    unsigned char* pbuf = reinterpret_cast<unsigned char*>(buffer);
    while (buflen > 0) {
        int numRead = read(sock, pbuf, buflen);
        if (numRead < 0) return -1;
        if (numRead == 0) return 0;
        pbuf += numRead;
        buflen -= numRead;
    }
    return 1;
}

Also, after reading the buffer, you are treating it as if it were null-terminated, but it is not, which is why you get extra garbage in your output.

More importantly, mapData != command.c_str() will ALWAYS be true, so your while loop iterates indefinitely (until a socket error occurs), which is not what you want. You want the loop to end when you receive a "command> " string instead.

mapData is initially NULL, and c_str() NEVER returns NULL, so the loop ALWAYS iterates at least once.

Then you allocate and free mapData but don't reset it to NULL, so it is left pointing at invalid memory. Which doesn't really matter, since your while loop is just comparing pointers. c_str() will NEVER return a pointer to memory that mapData ever points to.

To end your loop correctly, you need to compare the contents of mapData after reading, not compare its memory address.

Try this instead:

char *mapData = NULL;
uint64_t dataSize = 0;
const string command = "command> ";
bool keepLooping = true;

do {
    if (readAll(mySocket, &dataSize, sizeof(dataSize)) <= 0) {
        cerr << "**Error: could not read text size" << endl;
        return 1;
    }

    if (dataSize == 0)
        continue;

    mapData = new char[dataSize];

    if (readAll(mySocket, mapData, dataSize) <= 0) {
        cerr << "**Error: could not read text" << endl;
        delete[] mapData;
        return 1;
    }

    cout.write(mapData, dataSize);

    keepLooping = (dataSize != command.size()) || (strncmp(mapData, command.c_str(), command.size()) != 0);

    delete[] mapData;
}
while (keepLooping);

Alternatively:

string mapData;
uint64_t dataSize = 0;
const string command = "command> ";

do {
    if (readAll(mySocket, &dataSize, sizeof(dataSize)) <= 0) {
        cerr << "**Error: could not read text size" << endl;
        return 1;
    }

    mapData.resize(dataSize);

    if (dataSize > 0) {
        if (readAll(mySocket, &mapData[0], dataSize) <= 0) {
            cerr << "**Error: could not read text" << endl;
            return 1;
        }

        cout << mapData;
    }
}
while (mapData != command);

C: tcp recv not clearing old data, You are allocating 1024 bytes for message and never zeroing that data. You are just reading into the same buffer over and over. First pass it  A temporary storage area is called buffer. All standard input and output devices contain an input and output buffer. In standard C/C++, streams are buffered, for example in the case of standard input, when we press the key on keyboard, it isn’t sent to your program, rather it is buffered by operating system till the time is allotted to that program.

like @eozd pointed out, calling malloc and free in your loop is a bad idea since you use return statements. Your code may leak memory. You should ensure you call free before returns. Even better, you could declare your buffer outside of while loop, and use break instead of return, and call free if there was en error

Looking at your solution, it seems that the communication protocol involves sending data size first, followed by the actual data. How is data size written to the wire? You may need to convert it from network byte order.

To debug, you could print out the value of dataSize before every read to make sure that it is what you expect

C/C++: Full example of reading a whole binary file to buffer, The following example will read a binary in full and store it to a buffer in memory. This structure stores the pointer to the data and their size. struct Reading a file that exists and is not empty; Reading a non-existing file; Reading an empty file C/C++: Full example using a linked list with custom struct  Clearing buffer while reading in binary data from a server in C++ 0 I have a server that sends raw binary data to print a "map" that a user must traverse through, however, I am having trouble clearing out my buffer after each line read and thus keep getting residual data printed at the end of the shorter lines.

You should clear the buffer too. Add:

 memset(mapData, 0, dataSize);

after the malloc.

Pro .NET 1.1 Network Programming, Read(buffer, 0, bufferSize)) > 0) { writeStream. By default, uploading files to the server is not permitted. Read a binary file FileStream fs = new FileStream(0"c:\​tempVsample.bmp", FileMode. Clear(buffer, 0, bufferSize); count = stream. I have to open a binary file, read it's content, save the content into a buffer, allocate space on the heap with malloc, close the file and finally printf( the content of the .bin file). I came this far (closing file is not implemented yet):

Reading and writing binary file in C/C++, It is used to write a given number of bytes on the given stream, starting at the position of the put po writing binary file in C/C++. CC++Server Side ProgrammingProgramming To read a binary file in C++ use read method. It extracts a read. Then clear() can be used to reset the stream to a usable state. Prev Next. Buffer manipulation functions in C work on the address of the memory block rather than the values inside the address. Example programs for memset(), memcpy(), memmove(), memcmp(), memicmp() and memchr() functions are given below.

JavaScript: The Definitive Guide, Readable streams trigger events when data is ready. s.write(buffer); // Write binary data s.write(string, encoding) // Write string data. encoding is still open and writeable s.on("drain", f) // Call f() when internal buffer becomes empty As Node programs can often treat buffers as opaque chunks of data, reading them from  The following example will read a binary in full and store it to a buffer in memory. We used the custom structure binary_data_t to store the data information. This structure stores the pointer to the data and their size. struct binary_data_t { long size; void *data; }; In main.cpp we performed three tests…

Java Cookbook, On the other hand, if you are writing both ends, you can simply use println()—​followed always by an explicit flush() before you read— to prevent the deadlock of having both ends trying to read with one end's data still in the PrintWriter's buffer! If you need to process binary data, use the data streams from java.io instead of the  Dim stream As FileStream ' Streams the binary data to the FileStream object. Dim writer As BinaryWriter ' The size of the BLOB buffer. Dim bufferSize As Integer = 100 ' The BLOB byte() buffer to be filled by GetBytes. Dim outByte(bufferSize - 1) As Byte ' The bytes returned from GetBytes. Dim retval As Long ' The starting position in the BLOB output.

Comments
  • Is it possible that the inner while loop iterates more than once? If so, freeing buffer inside that loop is almost definitely incorrect.
  • On a couple of unrelated notes: You don't need the buffer variable. Pass &dataSize directly to the read call. Also pass sizeof dataSize instead of hard-coding 8. And don't forget that read will return 0 if the socket is close, something you need to handle as well. Lastly, if you use TCP sockets, then a single read call may return less than what was written, you need to call read in a loop until all requested data has been received.
  • Use the return value from read which is the number of bytes.
  • Worked perfectly! Only issue is its not printing out the "command> " itself but a little messing around should fix that. Thank you!
  • @ejscribner it should be printing out everything that is received. However, cout is usually buffered, so you may need to flush it once the command has been received, via cout << flush or cout.flush()
  • Before each line of actual data, it sends a size_t that represents how many bytes need to be read, however when I print the dataSize it prints the proper size (18 for line 1, then 10 for the rest of the lines) but still leaves the 'Miffy!' at the end of each of the remaining shorter lines.
  • what happens if you put memset(buffer, 0, datasize); right before free(buffer)?