What is the correct way of reading from a TCP socket in C/C++?

前端 未结 8 1412
后悔当初
后悔当初 2020-11-28 04:33

Here\'s my code:

// Not all headers are relevant to the code snippet.
#include 
#include 
#include 
#in         


        
相关标签:
8条回答
  • 2020-11-28 04:52

    Where are you allocating memory for your buffer? The line where you invoke bzero invokes undefined behavior since buffer does not point to any valid region of memory.

    char *buffer = new char[ BUFFER_SIZE ];
    // do processing
    
    // don't forget to release
    delete[] buffer;
    
    0 讨论(0)
  • 2020-11-28 05:01

    Several pointers:

    You need to handle a return value of 0, which tells you that the remote host closed the socket.

    For nonblocking sockets, you also need to check an error return value (-1) and make sure that errno isn't EINPROGRESS, which is expected.

    You definitely need better error handling - you're potentially leaking the buffer pointed to by 'buffer'. Which, I noticed, you don't allocate anywhere in this code snippet.

    Someone else made a good point about how your buffer isn't a null terminated C string if your read() fills the entire buffer. That is indeed a problem, and a serious one.

    Your buffer size is a bit small, but should work as long as you don't try to read more than 256 bytes, or whatever you allocate for it.

    If you're worried about getting into an infinite loop when the remote host sends you a malformed message (a potential denial of service attack) then you should use select() with a timeout on the socket to check for readability, and only read if data is available, and bail out if select() times out.

    Something like this might work for you:

    fd_set read_set;
    struct timeval timeout;
    
    timeout.tv_sec = 60; // Time out after a minute
    timeout.tv_usec = 0;
    
    FD_ZERO(&read_set);
    FD_SET(socketFileDescriptor, &read_set);
    
    int r=select(socketFileDescriptor+1, &read_set, NULL, NULL, &timeout);
    
    if( r<0 ) {
        // Handle the error
    }
    
    if( r==0 ) {
        // Timeout - handle that. You could try waiting again, close the socket...
    }
    
    if( r>0 ) {
        // The socket is ready for reading - call read() on it.
    }
    

    Depending on the volume of data you expect to receive, the way you scan the entire message repeatedly for the "end;" token is very inefficient. This is better done with a state machine (the states being 'e'->'n'->'d'->';') so that you only look at each incoming character once.

    And seriously, you should consider finding a library to do all this for you. It's not easy getting it right.

    0 讨论(0)
提交回复
热议问题