Thread: Getting the size of the client recv buffer

  1. #1
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    291

    Getting the size of the client recv buffer

    Hello, recently I have been working on a very very simple server, it works well but in some cases is unnecesarily slow. I was wondering if there's a standard call to the client to get the size of recv buffer, so I could adapt my send buffer to the max size instead of checking each time the received size. First I was thinking on send a huge string and use the 'client readed bytes' as max client buffer, but I can see that's a bad solution. I'm using winsock2, and I have taked a look at the ws2 manual reference but with no results.

    Thank's in advance
    Niara

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    No and No.

    Both sending and receiving can fragment the message, you have no control over that.

    If you call send() with a large buffer, you must look at the return result to see how much was actually sent, and if it's short, then call send() again with the remainder of the buffer until it's all sent.

    Likewise with recv(), you can supply a large buffer but recv() won't necessarily wait for it to be filled. Look at the return result to work out how much was received and act accordingly.

    If you think it will help, a common technique is to send the message length in front of the message, so you know pretty early on how much data to expect.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    291
    Hello Salem, thank's for the reply.

    I was thought that maybe there was a getclientbuffersize(). For now I'm using (and I will have to continue using) a variation of the beej guide 'sendall()' function. That's a simulation of a send process that I made for implement the function:

    Code:
    #include <conio.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int send(char* ,int );
    
    int main()
    {
    FILE *arx;
    char *bff=NULL;
    int ta,tb,tl,q;
    int total,restants,n;
    int inc;
    bool rm;
    
    arx=fopen("test.txt","rb");
    fseek(arx,0L,SEEK_END);
    ta=ftell(arx);
    fseek(arx,0L,SEEK_SET);
    
    tl=0;
    tb=27;
    bff=(char*)malloc(sizeof(char)*tb);
    
    inc=0;
    rm=false;
    while(tl<ta)
        {
        if(rm)
            {
            tb++;
            bff=(char*)realloc(bff,sizeof(char)*tb);
            rm=false;
            }
        
        for(q=0;q<tb;q++)
            {
            //if(feof(arx)!=0) {break;}
            if(tl>=ta) {break;}
            bff[q]=getc(arx);
            tl++;
            }
        bff[q]='\0';
        
        total=0;
        restants=strlen(bff);
        while(total<strlen(bff))
            {
            n=send(bff+total,restants);
            
            if(!rm && n==strlen(bff))
                {
                inc=1;
                rm=true;
                }
    
            if(n==-1) {break;}
            total+=n;
            restants-=n;
            }
        }
    
    if(bff) {free(bff);}
    send(NULL,0);
    
    fclose(arx);
    getch();
    return 0;
    }
    
    int send(char* data,int t)
    {
    static char complert[1024]="";
    int tb,q,bl=0;
    char  bff[10];
    
    if(!data) {printf("%s",complert);return 0;}
    
    (t<10) ? tb=t : tb=10;
    
    for(q=0;q<tb;q++)
        {
        bff[q]=data[q];
        bl++;
        }
    bff[q]='\0';
    sprintf(complert,"%s%s",complert,bff);
    return bl;
    }
    //linked/compiled with mingw & devcpp as a *.cpp
    it works with sokets simply using the sokets 'send' function instead my simulation call

    Code:
    n=send(thesocket,bff+total,restants,0);
    the modification is the buffer memory reallocation when the client's buffer is bigger than the server buffer, so I can send more bytes. The method is not completed because the server buffer is reallocated incrementing by 1, so if I could know the client buffer size I would be able to realloc at the exact size to optimze the sending process. Sure that I'm not be the first on think about that...

    Feel free to use/modify/comment/criticyze that code I posted

    Niara
    Last edited by Niara; 10-08-2006 at 02:07 PM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > #include <conio.h>
    The only compiler which needed this header file couldn't do network stuff, so why do you need it?
    It's an obsolete header.

    > bff=(char*)malloc(sizeof(char)*tb);
    Don't cast malloc in C
    See the FAQ

    Oh now I see
    > linked/compiled with mingw & devcpp as a *.cpp
    Use a C compiler for your C code then.
    Well it's all C except for your use of bool, and that's easy to fix.


    > (t<10) ? tb=t : tb=10;
    Mmm - if / else would have been clearer, as would
    tb = t < 10 ? t : 10;

    > sprintf(complert,"%s%s",complert,bff);
    Very few C functions (say memmove) work properly if the input and output overlap. Trying to sprintf into the same buffer as you're trying to read from as well is just a recipe for disaster.
    Especially as all you needed was strcat()

    > bff=(char*)realloc(bff,sizeof(char)*tb);
    Classic realloc mis-use.
    Always use a temp, and check it for NULL
    Code:
    temp = realloc ( oldptr, size );
    if ( temp ) oldptr = temp;
    else // panic
    > bff[q]='\0';
    You set tb to 10, so when you get here, q is 10
    Buffer overflow!
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    291
    Hello, more thanks for the reply.

    Step by step. I have used the conio.h only in the test while implementing the function (basically to call to 'getch()'), not in the real network code. The C mixed with some C++, it's a bad learning practice, I like C, but C++ is more flexible (I'm not expert in neither C nor C++, but since c++ compiler can compile c code -maybe something not, I don't know- I think that there can be any problem). i.e. I don't know how to work with files in cpp, then I do it in c; I like use vectors of structures but I don't know how to do it in c, then I do it in cpp;etc...
    The 'sprintf' over the same buffer, yes a very bad habit, I should use the 'strcat' instead. And the buffer overflow, I saw it while coding but never changed it.
    But the important thing on the code I posted is the sending process, verify the received bytes and resend the bytes left (my 'send' function is only a simulation, I never used out of that code).

    And I will add my own critic: I have seen now that a sending process like that only work with txt files, testing it with images does not work because of the '\0' that I add at the end of the strings, so I have modifyed a bit

    Code:
    bool sendTheFile(SOCKET s,char *ruta)
    {
    FILE *arx;
    char *bff=NULL;
    int ta,tb,tl,q,ba;
    int total,restants,n;
    bool rm,eok;
    
    if(!(arx=fopen(ruta,"rb"))) {return false;}
    fseek(arx,0L,SEEK_END);
    ta=ftell(arx);
    fseek(arx,0L,SEEK_SET);
    
    tl=0;
    tb=100;
    bff=(char*)malloc(sizeof(char)*tb);
    if(!bff) {return false;}
    rm=false;
    eok=true;
    while(tl<ta)
        {
        if(rm)
            {
            tb+=50;
            bff=(char*)realloc(bff,sizeof(char)*tb);
            if(!bff) {eok=false;break;}
            rm=false;
            }
        
        ba=0;
        for(q=0;q<tb;q++)
            {
            if(feof(arx)!=0) {break;}
            bff[q]=getc(arx);
            tl++;
            ba++;
            }
        
        total=0;
        restants=ba;
        while(total<ba)
            {
            n=send(s,bff+total,restants,0);
            if(!rm && n==ba)
                {
                rm=true;
                }
            if(n==-1) {break;}
            total+=n;
            restants-=n;
            }
        }
        
    if(bff) {free(bff);}
    fclose(arx);
    return eok;
    }
    Is the same as before, but I deleted the '\0' at the end of the buffer to send. Maybe is not 100% optimized, but it works (for the moment).

    Niara

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    ftell returns long - you put it into int. Not a good practice.

    And you don't check the resulting value for possible errors.

    Advice - use fread instead of the loop to fill the byte array from the file.

  7. #7
    Registered User
    Join Date
    Mar 2005
    Location
    Juneda
    Posts
    291
    Hey vart, thanks for your observation.

    I have already modifyed the code checking for the error return '-1' on the 'ftell()' function. I didn't realized that I was storing the file size on an 'int' (I have commented something similar: bad learning habits produce errors in such simple codes), I will have to correct that part.

    Niara

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. char Handling, probably typical newbie stuff
    By Neolyth in forum C Programming
    Replies: 16
    Last Post: 06-21-2009, 04:05 AM
  2. Adventures in labyrinth generation.
    By guesst in forum Game Programming
    Replies: 8
    Last Post: 10-12-2008, 01:30 PM
  3. Client works on a LAN but don't send all the data
    By Niara in forum Networking/Device Communication
    Replies: 9
    Last Post: 01-04-2007, 04:44 PM
  4. Error with a vector
    By Tropicalia in forum C++ Programming
    Replies: 20
    Last Post: 09-28-2006, 07:45 PM
  5. AdjustWindowRect/Setting client size
    By JaWiB in forum Windows Programming
    Replies: 4
    Last Post: 06-23-2006, 11:43 PM