Progress bar in Winsock transfer file

Hi, i have a server-client program wich sends a file, and i'd like to add a progress bar to it and i don't know how to do it.
Here's the file receive function


cout<<"Receiving file..."<<endl;

int Size;
char Filesize[MAX_PATH] = "\0";
char name[512] = "\0";

recv(this->server, name, sizeof(name), 0);

if(recv(this->server, Filesize, sizeof(Filesize), 0)) // File size
{
Size = atoi((const char*)Filesize);
cout<< "File size: "<< Size<<endl;
}

char *Buffer = new char[Size];
recv(this->server, Buffer, Size, 0);

char cmd[50];
cout<<"Adress to save file: "<<endl;
cin>>ws; cin>>cmd;

FILE* File;
File = fopen(cmd, "wb");
fwrite(Buffer, 1, Size, File);
fclose(File);

cout<<"File received"<<endl;
free(Buffer);

I read i could set the size of the file as the max value of the progress bar, i do have the file size, but how do i read the file as it's being received to make the progress bar?
Thanks.
you can get the # of bytes you got from the network call. recv should tell you how many bytes are in the payload. Just keep a running total of that against the file's size.

or just do like every other windows program:

1
2
3
4
5
6
7
8
9
void foo()
{
    set progress bar to 10%;
    for()
     {
          //do the work for 1/2 an hour
     }
    set progress bar to 90%;
}


kidding aside, avoid updating a gui progress bar widget more than a few times (say, 5) per second. Its an approximation and a "hey user i am still here and working on it" device, not a real time graph. You can greatly reduce your progress/ performance by spamming the counter if you get carried away and update every loop if the loop is executing fast.
Last edited on
@jonnin it's a console app and the files aren't too big. Maybe i can try something like this:
if recv(this->server, Filesize, sizeof(Filesize), 0) < size
char a = *
cout << a

but i don't know if the recv is going to allow me to compare it with the size variable

Last edited on
you wouldn't do that. you need to store what recv got in a counter, and compare that to the file size. This is because some files may be fetched with many calls to recv, and you need a running total to get your progress. If they all fit in one packet, you don't have to worry about it. If they all fit in one packet, you will spend more time drawing progress than you will handling the file!

I would just write a char padded % to the console. you can write backspaces to remove the previous value and rewrite it, many old console progams did it this way. Some also have a 'spinner' animation of something like / | \ and a horizontal bar etc over and over makes it look like a rotating thing...

eg
cout << percent; //lets say you set this to 2 digits, and if < 10 put a space in front.
cout << "\b\b"; //backspace. now you can 'update' the percent...
it may need a flush to keep it honest:
cout.flush();
Last edited on
And this should go with no loop? I don't understand where it would fit in my code, i should place it between File = fopen(cmd, "wb") and fwrite(Buffer, 1, Size, File); ?
Also, it has to be on a loop, right? To test it i have a 500mb file that takes about 10 secs to transfer it

what about this SendProgress event?
https://docs.microsoft.com/en-us/previous-versions/visualstudio/aa228060(v=vs.60)?redirectedfrom=MSDN
could implement that? the thing is there is no example
presumably you have a loop of recv commnads, to get all the packets for a file (??). It would go there ... every time you get a packet, you can update, or every N packets more likely given the rate of transfer these days. It would go in that loop where you call recv.

you can try sendprogress. I haven't used it, but surely someone on the web has an example.
It may be obsolete if you found it in something called 'previous versions'... but most everything from 32 bit era (win 95+) still works fine if you are willing to throw an old library in your path here and there. Its not great practice to use old stuff, if you can avoid it.
Last edited on
Well recv() makes no guarantees about filling your buffer.

You can make it a blocking socket, at which point your choices are 0% and 100%.

Or you make it a non-blocking socket, fetch messages in blocks and update progress accordingly.
1
2
3
4
5
6
7
char buff[4096];
int totalSoFar = 0;
while ( (n=recv(this->server,buff,sizeof(buff),0) > 0 ) {
  fwrite(buff, 1, n, File);  // output to file
  totalSoFar += n;
  percentComplete = totalSoFar * 100 / FileSize;
}
Topic archived. No new replies allowed.