c++mobiletcptcpserver

TCP need to discard info on the buffer or make it faster


I am making a 3d application that works with the data of the accelerometer and gyroscope of the mobile. The problem is that the mobile sends data faster than the computer reads. The application increasingly makes the movements of the mobile with more delay as time passes. For example, at the beginning 2~3s is faithful to what the mobile does in reality, but over 10s it is making the movements that I did 6 seconds before.

I understand that it is reading data from the beginning buffer while the front of the most current data grows and never reaches it. I think the problem is how I read the data that comes to me.

Here is an example code that is implemented in the application. What could I do?

#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include <algorithm>

#define PORT 8080

int main(int argc, char const *argv[])
{
        int server_fd, new_socket, valread;
        struct sockaddr_in address;
        int opt = 1;
        int addrlen = sizeof(address);
        char buffer[1024] = {0};

        const char *ACK = "ACKDAT\n";

        std::string data;

        socklen_t len;
        char *error;

        if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
        {
                perror("socket failed");
                exit(EXIT_FAILURE);
        }

   
        if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,&opt, sizeof(opt)))
        {
                perror("setsockopt");
                exit(EXIT_FAILURE);
        }
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = INADDR_ANY;
        address.sin_port = htons( PORT );

        if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
        {
                perror("bind failed");
                exit(EXIT_FAILURE);
        }
        if (listen(server_fd, 3) < 0)
        {
                perror("listen");
                exit(EXIT_FAILURE);
        }
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0)
        {
                perror("accept");
                exit(EXIT_FAILURE);
        }

        fcntl(new_socket, F_SETFL, O_NONBLOCK);

        while(true){
                valread = read( new_socket , buffer, 1024);
                for(int i = 0;i < 1024 ; i++){
                        if(buffer[i]!=0){
                                data = data + buffer[i];
                        }
                        buffer[i]=0;
                }
                if(!data.empty()){
                        //remove /n from data
                        data.erase(std::remove(data.begin(), data.end(), '\n'), data.end());
                        std::cout<<"#"<<data<<"#"<<std::endl;
                        send(new_socket , ACK , strlen(ACK) , 0 );
                }
                data.clear();
        }
        return 0;
}

Solution

  • While Sam Varshavchik's suggestion of using a thread is good, there's another option.

    You already set your socket to non-blocking with fcntl(new_socket, F_SETFL, O_NONBLOCK);. So, at each loop you should read everything there is to read and send everything there is to send. If you don't tie one-to-one the reading and writing, both sides will be able to catch up.

    The main hint that you need to fix this is that you don't use the read return value, valread. Your code should look like:

    while(true){ // main loop
    
    ...
    
    valread = read( new_socket , buffer, 1024);
    while(valread > 0)
    {
        // deal with the read values.
        // deal with receiving more than one packet per iteration
    }
    // send code done a single time per loop.
    

    There still plenty of architecture you need to have a clean resilient main loop that sends and receives, but I hope that points you in a useful direction.