Why is there a delay when sending data to SIMULINK

2019-09-07 07:28发布

Hi I'm trying to send data from simulink to a c++ program, and then send it back as part of a larger program. I've attached the code here. The problem is in the write function of sock_send class. When printing to screen, value from data_o is perfect and appears normal, but while sending it using the linux "send" function, the values are very delayed. They only appear after sometime in the simulink scope. I think I'm missing something very trivial. Any help would be appreciated.

This is my main program.

#include "sock_send.h" 
#include <thread>
#include <functional>
#include <iostream>

extern std::mutex some_other_mutex;

int main(){

    int portno[2] = {55011, 55021};
    double pdiesel ={0.002};

    sock_send newsocket1;
    sock_send newsocket2;

    newsocket1.startsocket(portno[0]);
    newsocket2.startsocket(portno[1]);

    std::thread t1 (&sock_send::readsocket, &newsocket1, std::ref(pdiesel));

    std::thread t2 (&sock_send::writesocket, &newsocket2, std::ref(pdiesel));


    t1.join();
    t2.join();

    return 0;

}

The sock_send.h program

#ifndef SOCK_SEND_H
#define SOCK_SEND_H

#include <functional>
#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <mutex>
#include <vector>
#include <thread>
#include <chrono>

extern std::mutex some_other_mutex;


class sock_send
{

public:

    void startsocket (int portno);
    void writesocket(double & data_o);
    void readsocket(double & data_in);
    ~sock_send();

private:
    struct sockaddr_in serv_addr, cli_addr;
    int n, epfd, sockfd, yes=1, newsockfd = 0, nbytess,
    clilen = sizeof(cli_addr);
    // define epoll event structs
    struct epoll_event event, *events = new epoll_event;


};
#endif

and the sock_send.cc program

#include "sock_send.h"

std::mutex some_other_mutex;

void sock_send::startsocket (int portno){

    //create an epoll file descriptor
        if ((epfd = epoll_create1(0)) == -1)
        std::cout << "Error on epoll create\t" << errno << std::endl;

    //create the socket file descriptor
    if ((sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) == -1) 
        std::cout << "Error on socket create\t" << errno << std::endl;

        // get rid of annoying port in use
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) 
        std::cout << "Error on socket reuse option\t" << errno << std::endl;

    // fill up serv addr with zeros
        bzero((char *) &serv_addr, sizeof(serv_addr));

        //enter data in serv addr
        serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    // bind port and ip to socket 1
    if ((bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) == -1) 
        std::cout << "Error on binding sock\t" << errno << std::endl;

        //start listening on socket           
    if ((listen(sockfd,100))==-1)
        std::cout << "Error on listen sock\t" << errno << std::endl;

    // socket epoll control
    event.data.fd = sockfd;
    event.events = EPOLLIN;

    if ((epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &event)) == -1) 
        std::cout << "Error on epoll ctl sock\t" << errno << std::endl;

        while (newsockfd == 0){     

        // wait for an event using epoll
            if ((n = epoll_wait (epfd, events, 20, -1)) == -1){
            std::cout << "Error on epoll wait\t" << errno << std::endl;
            continue;
        }
        if (sockfd == events[0].data.fd){   

            // accept incoming connection
                if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,(socklen_t*)&clilen)) == -1){
                std::cout << "Error on accept\t " << errno << std::endl;
                continue;
            }
            event.data.fd = newsockfd;                  
            event.events = EPOLLIN;
                if ((epoll_ctl (epfd, EPOLL_CTL_ADD, newsockfd, &event)) == -1){
                std::cout << "Error on epoll cntl" << errno << std::endl;
                continue;
            }
            break;
        }

        else
            std::cout << "Epoll returning some other socket \t" << events[0].data.fd << std::endl;
    }
}

void sock_send::readsocket(double & data_in){
    while (1){  

        // wait for an event using epoll
            if ((n = epoll_wait (epfd, events, 20, 0)) == -1){
            std::cout << "Error on epoll wait\t" << errno << std::endl;
            continue;
        }

        //if newsock connections available
        if (newsockfd == events[0].data.fd){

            std::unique_lock<std::mutex> lck (some_other_mutex);
            nbytess = recv(events[0].data.fd, &data_in , sizeof data_in, 0);
            lck.unlock();
            std::this_thread::sleep_for(std::chrono::microseconds(1000));                                       
            if (nbytess == -1){
                std::cout << "Error during read: " << errno << std::endl;
                break;
            }

            if (nbytess == 0){
                std::cout << "End of data from this socket" << std::endl;
                break;
            }    
        }
    }
}


void sock_send::writesocket(double & data_o){
    while(1){
        std::unique_lock<std::mutex> lck (some_other_mutex);
        nbytess = send(newsockfd, &data_o, sizeof data_o, 0);
        std::cout << data_o << "\t" << data_o<< "\t" << sizeof data_o << std::endl;
        lck.unlock();
        std::this_thread::sleep_for(std::chrono::microseconds(1000));                                           
        if (nbytess == -1){
            if (errno == 104)
                std::cout << "Connection Closed" << std::endl;
            else
                std::cout << "Error during write: " << errno << std::endl;
        }
    }
}

sock_send::~sock_send()
{   
    delete events;
    close (sockfd);
}

and the simulink model

simulink model

Remote addresses are both localhost, port nos as given in main, byte order is little Endian, sample times for sine wave and tcp rx block are 1e-3 and simulation time is 10 secs

edit:

I figured out how to remedy the issue by using

std::this_thread::sleep_for(std::chrono::microseconds(1)); 

instead of

std::this_thread::sleep_for(std::chrono::microseconds(1000)); 

in the writesocket function. The issue still stands though as I'm not sure why it happens. All my sampling times are 1 millisecond. I guess there is a deadlock situation occurring? I would be grateful if someone could provide an explanation.

0条回答
登录 后发表回答