0

I am creating a personal remote file explorer for me and my buddy to mess around with. For the most part it works as intended, it enumerates through the given directory and sends it back for the server to see. The problem is that if the buffer receives more than 46 bytes, it will overwrite the remaining buffers into weird ASCII strings.

What Client Sends - C:\Users\Test\NTUSER.DAT{53b39e88-18c4-11ea-a811-000d3aa4692b}.TM.blf Size: 69

What Server Sees - C:\Users\Test\NTUSER.DAT{53b39e88-18c4-1■◄_y·⌂ Size: 46

The Default Buffer Size for both programs are 512 bytes

EDIT: Before you ask FileManager is personal code, only thing it does for client is gather paths in string for client to send to server.

Client Send Code

        //Gets Path From Server(recvbuf&recvbuflen buffer size = 512)
        std::string fldr = GetReply(ConnectSocket, recvbuf, recvbuflen);
        std::cout << "Reply: " << fldr << "\n";
        //Gets Directory Struct using given path from server
        FileManager::Directory* dir = f.GetDir(fldr);
        //Sends initial size to iterate through on server side
        send(ConnectSocket, std::to_string(dir->TotalList.size()).c_str(), dir->TotalList.size(), 0);
        //dir->TotalList holds a vector of strings that contain paths in directory
        for (std::string rV : dir->TotalList) {
            //Sleep for 75ms, without it the data would be sent to fast
            Sleep(75);
            //Sends the elements in TotalList
            //had to use sizeof(rV) because (int)strlen would overwrite the buffer fsr
            send(ConnectSocket, rV.c_str(), sizeof(rV), 0);
            std::cout << "Sent: " << rV << " Size: " << (int)strlen(rV.c_str()) << "\n";
        }

Server Recv Code

        while (1) {
            //Send Command, memset(sndbuf, 0, sizeof(sndbuf) is called before loop
            std::cout << "\n\nEnter Folder: "; std::cin.getline(sndbuf, sizeof(sndbuf));
            //DirList is a string vector holding all the previous paths that clients sent
            //CheckIfExists iterates through the vector and checks if sndbuf is a valid path
            //if false it restarts loop
            if (CheckIfExists(sndbuf, DirList)) {
                //if true sends path, again if I used (int)strlen(sndbuf)
                //instead of sizeof(sndbuf) it would cause it to overwrite
                //the buffer on client side, again idky
                send(cSock, sndbuf, sizeof(sndbuf), 0);
                //zeros out the buffer for the replys from client
                memset(recvbuf, 0, sizeof(recvbuf));
                //Display reply loops recv and clears then adds new elements to vector
                DisplayReply(cSock, recvbuf, recvbuflen, &DirList);
                break;
            }
            else
                std::cout << "Folder Doesn't Exist...";
        }

Server DisplayReply Code

void DisplayReply(SOCKET cSock, char* recvbuf, int recvbuflen, std::vector<std::string>* list) {
    //Gets the # of paths client has
    int r = std::stoi(GetReply(cSock, recvbuf, recvbuflen));
    std::cout << "Size: " << r << "\n";
    //Again zeroing the buffer, then clearing the vector
    memset(recvbuf, 0, sizeof(recvbuf)); list->clear();
    for (int i = 0; i < r; i++) {
        //Sleep for 75ms so all data sends properly
        Sleep(75);
        //Recieve replys from client, GetReply returns string
        //Using any other variable doesnt work either, all caps out at 46 bytes
        //ex const char* or char*
        std::string rV = GetReply(cSock, recvbuf, recvbuflen);
        std::cout << rV << " Size: " << (int)strlen(rV.c_str()) << "\n";
        //Add path to vector using vector pointer
        list->push_back(recvbuf);
    }
}

Server GetReply Code

std::string GetReply(SOCKET cSock, char* recvbuf, int recvbuflen) {
    int iResult = 0;
    do {
        iResult = recv(cSock, recvbuf, recvbuflen, 0);
        if (iResult > 0) {
            return (std::string)recvbuf;
        }
        else {
            printf("recv failed with error: %d\n", WSAGetLastError());
            return "";
        }

    } while (iResult > 0);
}
Ken White
  • 123,280
  • 14
  • 225
  • 444
GenZKaren
  • 37
  • 5
  • 5
    `sizeof(rV)` is the size of the `std::string` object which is constant and has no relation to the amount of data it is storing. Use `rv.size()` There's no good reason to use `strlen` with a `std::string` ever. There are probably other issues based on comments about `strlen` and `sizeof` that don't make sense. Consider a [mcve] so we can see the definitions of all of the variables in use. – Retired Ninja Oct 21 '22 at 02:50
  • ok ill try that, but its still bad even if strlen is returning the size of the const char* of the given string? – GenZKaren Oct 21 '22 at 02:55
  • @RetiredNinja if I call rv.size() on client before i send data to server it causes the server to recieve extra text to the buffer which was a problem I had earlier until I just called sizeof(rV) ex. `send(ConnectSocket, rV.c_str(), sizeof(rV), 0);` produces `C:\Users\Test` while `send(ConnectSocket, rV.c_str(), rV.size(), 0);` produces `C:\Users\Testrr` – GenZKaren Oct 21 '22 at 03:00
  • If the `std::string` contains binary data with embedded zeroes then `strlen` will be incorrect but `size()` will not. If the `std::string` doesn't contain embedded zeroes then `strlen` should return the same value but it will have taken linear time based on the length of the string where `size()` is constant time. In any case a C++ programmer will look at code with `strlen` and sadly shake their head as another small part of them dies inside. – Retired Ninja Oct 21 '22 at 03:00
  • @RetiredNinja ok, I understand what you are trying to say. I will remove it and use .size() for checking size of string but im still having trouble getting the right data through. This was never an issue for me a few years back when I created something like this but more complex, however this basic stuff is killing me... I was able to debug until this point which is why im super confused on why once the recv buffer on server reaches 46 bytes it messes up. I read up on recv and send saying that it could only send so much at one time but im sure that isnt the case here. Its just 46 bytes – GenZKaren Oct 21 '22 at 03:05
  • Also, you should send the size of the data in the first 4/8 bytes, then receive the data based on that size, using a fixed size buffer is not good – thedemons Oct 21 '22 at 03:07
  • 1
    As I said earlier, it sounds like there are other issues in your program but without a [mcve] we can't help diagnose them. – Retired Ninja Oct 21 '22 at 03:08
  • 2
    Warning: If you are using a streaming protocol like TCP you can't count on receiving a complete message with a single call to `recv`. Streams don't care about your messages. They send what they have, fragment large messages into multiple packets, pack smaller messages into a single packet, and generally do whatever they want to do. That `recv` call could contain all of a message, part of a message, the end of one message and the beginning of the next, a whole bunch of small messages, or just about any combination thereof, so long as all of the data is sent in order. – user4581301 Oct 21 '22 at 04:02
  • 2
    *"FileManager is personal code, only thing it does for client is gather paths in string for client to send to server."* -- sounds like you could remove this from your [mre]. Instead of trying to demonstrate what your program is supposed to do, demonstrate sending a string that triggers the problem. Try starting from `std::string rV = "C:\Users\Test\NTUSER.DAT{53b39e88-18c4-11ea-a811-000d3aa4692b}.TM.blf";` proceeding to `send(ConnectSocket, rV.c_str(), sizeof(rV), 0);` `std::cout << "Sent: " << rV << " Size: " << (int)strlen(rV.c_str()) << "\n";` and eliminating the rest of your send code. – JaMiT Oct 21 '22 at 04:57

1 Answers1

0

You most likely zeroed the buffer where you didnt have too.

JohnySiuu
  • 156
  • 6