Thread: Not receiving everything

  1. #1
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217

    Not receiving everything

    Im making a small set of socket classes and i was testing a piece of code to see if ReadLine() works. Here's the code that works:

    Code:
        TcpSocket sock;
    
        if(sock.Connect(IpAddress::ResolveHost("www.google.com.au"), 80))
        {
            char recvBuff[4096];
            sock.Write("GET / HTTP/1.1\n");
            sock.Write("Host: www.google.com.au\n");
            sock.Write("Connection: close\n");
            sock.Write("\n");
    
            while(sock.ReadLine(recvBuff, sizeof(recvBuff)))
                printf("Line: %s\n", recvBuff);
        }
        return 1;
    I figured it should also work if i change the size of "recvBuff" to 10, but it only receives part of the header (instead of both header and data) before the programs finishes. The output is this:

    Code:
    Line: HTTP/1.1
    Line: 200 OK
    Line: Cache-Con
    Line: trol: pri
    Line: vate, max
    Line: -age=0
    Line: Date: Wed
    Line: , 11 Jun
    Line: 2008 04:1
    Line: 6:06 GMT
    The read line code that i wrote is this:

    Code:
    bool soxTcpReadLine(unsigned int socketId, char* out, size_t outLen)
    {
        size_t recvCount = 0;
        while(recvCount < outLen - 1)
        {
            char byte;
    
            if(recv(socketId, &byte, 1, 0) > 0)
            {
                if(byte != '\n')
                    out[recvCount++] = byte;
                else break;
            } else break;
        }
    
        if(recvCount)
        {
            //Trim line
            while(recvCount)
            {
                if(out[recvCount - 1] < ' ')
                    out[--recvCount] = 0;
                else break;
            }
    
            //Null terminate
            out[recvCount] = 0;
            return true;
        }
        return false;
    }
    Last edited by 39ster; 06-10-2008 at 10:19 PM.

  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
    Do you have a non-blocking socket?

    In which case, recv() can return an error, and the error code will be something like EAGAIN, which means there's nothing right now, come back later.
    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
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Nope, it's blocking.

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    you need to be check the return value of recv. if it does return an error, the data is basically useless to your program *anyway* - it would probably be a good idea to throw an exception at that point (possibly unpacking errno into some user-friendly message as well). another thing I noticed is that you treating '\n' as your eol. remember that HTTP uses '\r\n' to delineate lines. also, single-transfer connections are typically shutdown after reading/writing the entire message. finally, reading a single byte from a TCP connection is horribly inefficient. I would recommend reading the entire message into a buffer before parsing each line out.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  5. #5
    Registered User
    Join Date
    Apr 2007
    Location
    Sydney, Australia
    Posts
    217
    Quote Originally Posted by Sebastiani View Post
    you need to be check the return value of recv. if it does return an error, the data is basically useless to your program *anyway* - it would probably be a good idea to throw an exception at that point (possibly unpacking errno into some user-friendly message as well). another thing I noticed is that you treating '\n' as your eol. remember that HTTP uses '\r\n' to delineate lines. also, single-transfer connections are typically shutdown after reading/writing the entire message. finally, reading a single byte from a TCP connection is horribly inefficient. I would recommend reading the entire message into a buffer before parsing each line out.
    Well the read line should support headers that use "\r\n" and "\n" as it trims the end of the string (removing any "\r"s).
    How inefficient is it to read one byte at a time? Would it be better to peek the data, find the end of the line, then receive? I would like to know how other api's handle read line.

  6. #6
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Code:
    sock.Write("GET / HTTP/1.1\r\n");
    (Same for the rest of the newlines... capture some live HTTP traffic, and examine it.)
    How inefficient is it to read one byte at a time?
    When some poster at another forum noted larger throughput with bigger calls to recv(), and asked why:
    Quote Originally Posted by Brian
    Why is it faster to drink a liter of water a cupful at a time than to drink it out of an eyedropper?
    Read and write as much as you can.

    I would like to know how other api's handle read line.
    Quote Originally Posted by Sebastiani
    I would recommend reading the entire message into a buffer before parsing each line out.
    That's how I'd do it.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. CTabCtrl not receiving messages
    By VirtualAce in forum Windows Programming
    Replies: 3
    Last Post: 07-23-2009, 09:37 AM
  2. Replies: 1
    Last Post: 03-21-2008, 08:15 PM
  3. data at fifo's receiving end has arrived?
    By quickNitin in forum Linux Programming
    Replies: 3
    Last Post: 11-05-2006, 03:19 AM
  4. Receiving characters on serial port
    By Roaring_Tiger in forum Networking/Device Communication
    Replies: 3
    Last Post: 07-01-2004, 01:52 PM
  5. receiving stderr and stdout from popen
    By rotis23 in forum C Programming
    Replies: 1
    Last Post: 11-08-2002, 08:21 PM