Search code examples
c++socketsnetwork-programmingsendrecv

recv() not getting all data sent by client using send()


I really have no idea if this is some sort of delay of the network, my pc, or whatever, I'm quite new to socket programming and have been trying to make this work for a while, implementing a simple framework to ease my work in a future project for my class and I use these functions in the problem I'm having:

void TCPSocket::send(const std::string& message, int flags) {

    if (isListening || !isConnected) {
        throw ConnectionException("Can't send message from a socket that is not connected");
    }

    int msgLength = message.length();
    int bytesLeft = msgLength;
    int bytesSent;
    const char* cMessage = message.c_str();

    while (bytesSent < msgLength) {

        const char* cMessageLeft = cMessage + bytesSent;

        int result = ::send(socketFd, cMessageLeft, bytesLeft, flags);
        if (result == -1) {
            throw ConnectionException("Could not send message. Error: " + std::string(strerror(errno)));
        }

        bytesLeft -= result;
        bytesSent += result;

    }

}

std::string TCPSocket::recv(unsigned int maxlen, int flags) {

    if (isListening || !isConnected) {
        throw ConnectionException("Can't receive message in a socket that is not connected");
    }

    char buffer[maxlen+1];
    int result = ::recv(socketFd, buffer, maxlen, flags);

    if (result == -1) {
        throw ConnectionException("Could not receive message. Error: " + std::string(strerror(errno)));
    }
    if (result ==  0) {
        isConnected = false;
        throw ClosedConnection("Client closed connection.");
    }
    buffer[result] = '\0';
    std::string message(buffer);

    return message;

}

It works great with just one message, I receive and send using different executables with no problem at all, but I've tried sending more than 1 message and my problem started, sometimes I get the server to receive 1 message, sometimes it gets none and when I add only a few printf()s it receives them all, could someone please explain to me why this happens?

Client code:

int main() {
    TCPSocket cl1(0);

    try {
        cl1.connect("localhost", 1170);
        for (int i = 0; i < 5; i++) {
            //printf("Esperando 5s... ");
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            //printf("Pronto!\n\n");

            cl1.send("Thank you!\n");
            //printf("Msg enviada\n\n");

        }
        cl1.close();
    }
    catch( std::exception &e) {
        std::cout << e.what() << std::endl;
    }
}

Server code:

int main() {
    TCPSocket sv1(0);

    try {
        sv1.bind(1170);
        sv1.listen();
        TCPSocket client = sv1.accept();
        printf("Cliente conectado\n");
        try {
            for (;;) {
                //client.send("Welcome !\n");
                std::cout << client.recv(256) << std::endl;
            }
        }
        catch (const ClosedConnection & x) {
            printf("Connection closed\n");
        }

    }
    catch( std::exception &e) {
        std::cout << e.what() << std::endl;
    }
}

If I uncomment the printfs on the client's code, all data is received on server.

Clarifying, I am sending the message with a 5s interval, still recv() only reads the first one and it blocks until client finishes it execution, never reading the rest of the messages that should be in the buffer. For some reason having printfs on the client's code make the applications run fine.


Solution

  • You don't seem to be initializing bytesSent so the number of times it would actually send the data seems indeterminate.

        int bytesSent = 0;