Home > front end >  TCP need to discard info on the buffer or make it faster
TCP need to discard info on the buffer or make it faster

Time:03-25

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;
}

CodePudding user response:

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.

CodePudding user response:

You can have all reading from the socket done in a separate std::thread, that does nothing but read from the socket and save the data in your program's internal buffer. Your existing program reads from the internal buffer, rather than a socket, whenever it is capable of doing so.

If the internal buffer is full you'll have to figure out what to do about it, probably discard unwanted data. Perhaps stash a copy of the most recent received record, in a safe place, and put it into the buffer when things get unclogged. The dedicated execution thread will likely need to do some minimal processing, to parse the raw data from the socket into some meaningful, logical form. It's unlikely that you can simply throw away random parts of the raw data stream from the socket. It will need to be logically parsed, in some form or fashion that's particular to your application, so this can be done in a meaningful way.

You will need to implement your application's buffer in a thread-safe manner, so that it can be simultaneously accessed by multiple execution threads. If you're not familiar with multi-threaded programming in C , you will find more information in your C textbook, on this topic.

  • Related