当TCP服务器正在等待数据时,如何使程序每10毫秒读取一次传感器

时间:2019-05-07 21:30:39

标签: c multithreading sockets tcp

我的程序需要每10毫秒读取一次传感器数据,并通过TCP套接字将其发送到客户端。该程序是用C语言编写的。 tcp服务器和传感器读取代码位于同一c文件中。服务器不会定期发送数据。而是,它等待来自客户端的数据请求(每50毫秒)。服务器收到请求后,便将数据发送到客户端。

我的问题是我需要每10毫秒读取一次传感器并将其保存在缓冲区中。服务器收到请求后,将缓冲区中的传感器数据发送给客户端。但是当tcp服务器正在等待请求时,整个程序都停留在read函数上:

n = read(newsockfd,buffer,31)

然后,我看不到传感器。

我试图将线程用于传感器读取和tcp服务器。它适用于读取传感器。但是,如果我在tcp服务器线程中添加任何usleep()(例如5毫秒),则在将数据发送到客户端之前需要5毫秒。

我的程序需要tcp服务器在收到请求后立即将数据发送到客户端。同时,每10毫秒读取一次传感器。任何人都有更好的解决方案吗?

tcp服务器和传感器读取的代码如下:

#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

#define MAX_SIZE 256
#define SAMPLE_RATE 



void read_sensor(void) {
    printf("read sensors\n");
}


int main() {

     int sockfd, newsockfd, portno = 10000, clilen;
     char buffer[MAX_SIZE];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     int data;

     printf( "using port #%d\n", portno );

     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
         printf("ERROR opening socket\n");
     bzero((char *) &serv_addr, sizeof(serv_addr));

     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons( portno );
     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
       error( const_cast<char *>( "ERROR on binding" ) );
     listen(sockfd,5);
     clilen = sizeof(cli_addr);

     while (1) {
        printf( "waiting for new client...\n" );
        if ( ( newsockfd = accept( sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen) ) < 0 )
            printf("ERROR on accept");
        printf( "opened new communication with client\n" );

        clock_gettime(CLOCK_REALTIME, &gettime_now);
        start_time = gettime_now.tv_nsec;       //Get nS value
        while (1) {
             int n = 0;
             if ( (n = read(newsockfd,buffer,31) ) < 0 ) //read data
                printf("ERROR reading from socket");
             buffer[n] = '\0';

             if (n > 0)
                printf("%s\n", buffer);
             else {
                break;             
             }

             if ( (n = write( newsockfd, buffer, strlen(buffer) ) ) < 0 ) //send data
                printf( "ERROR writing to socket\n");
             buffer[n] = '\0';

        }
        close( newsockfd );
     }


     return 0; 
}

1 个答案:

答案 0 :(得分:2)

您可以使用selectpoll等待数据到达,并且超时。

例如,如果您需要从现在起5毫秒内读取传感器,则可以在5毫秒的超时时间内调用pollselect。如果套接字接收到数据,它将立即返回并告诉您。否则,它将在5毫秒后返回,您将知道没有数据。

poll的示例:

struct pollfd pollfd = {.fd = socket_fd, .events = POLLIN};
int err = poll(&pollfd, 1, milliseconds_timeout);
// error check here; if err is negative then the error code is in errno
if (pollfd.revents & POLLIN) {
    // Socket received data
}
// Otherwise it didn't.
// Note that if data was received, it might not be time to read the sensors yet.
// You should keep poll()ing until it's the right time to read the sensors, using clock_gettime to check the time.