【问题标题】:How to send transmit timestamps along with data payload?如何发送传输时间戳和数据有效载荷?
【发布时间】:2021-06-22 21:52:23
【问题描述】:

我正在尝试发送数据包的传输时间戳来计算延迟。感谢Linux, UDP datagrams, and kernel timestamps: Lots of examples and stackoversflow entries later, and still cannot get timestamps at all,我可以在发送和接收数据报时获得时间戳。但是,本条目中的demo只能在sender中获取发送时间戳,在receiver中获取接收时间戳。我想知道如何发送数据报和传输时间戳,以便在接收器中同时获得传输和接收时间戳?我已经阅读了https://www.kernel.org/doc/Documentation/networking/timestamping.txt 文档,但我没有找到可能有帮助的东西。任何人都可以对此有想法吗?

谢谢!

【问题讨论】:

  • 您可能对NTP感兴趣

标签: c linux sockets timestamp udp


【解决方案1】:

您必须将时间戳的字节存储在您的消息中(开头是最好的,最好是在您自己的标头中,以及其他重要信息)。请参见下面的示例:

客户

#include <stdio.h>      // Default System Calls
#include <stdlib.h>     // Needed for OS X
#include <string.h>     // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h>       // To control the timeout mechanism

int main( void )
{
    int fd;
    if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket failed");
        return 1;
    }

    struct sockaddr_in serveraddr;
    memset( &serveraddr, 0, sizeof(serveraddr) );
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons( 50037 );
    serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );


    int n = (int)time(NULL);
    unsigned char timestamp[4];
    timestamp[0] = (n >> 24) & 0xFF;
    timestamp[1] = (n >> 16) & 0xFF;
    timestamp[2] = (n >> 8) & 0xFF;
    timestamp[3] = n & 0xFF;

    unsigned char buffer[256];
    memset(buffer, 0, sizeof(buffer));
    unsigned char s[6] = "hello\0";
    memcpy(&buffer, &timestamp, 4);
    memcpy(&buffer[4], &s, strlen(s));


    for ( int i = 0; i < 2; i++ ) {
        if (sendto( fd, buffer, strlen(buffer), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
            perror( "sendto failed" );
            break;
        }
        printf("message sent\n" );
    }

    close( fd );
}

服务器

#include <stdio.h>      // Default System Calls
#include <stdlib.h>     // Needed for OS X
#include <string.h>     // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h>       // To control the timeout mechanism

int main( void )
{
    int fd;
    if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror( "socket failed" );
        return 1;
    }

    struct sockaddr_in serveraddr;
    memset( &serveraddr, 0, sizeof(serveraddr) );
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons( 50037 );
    serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );

    if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
        perror( "bind failed" );
        return 1;
    }

    char buffer[200];
    for ( int i = 0; i < 100; i++ ) {
        int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );
        if ( length < 0 ) {
            perror( "recvfrom failed" );
            break;
        }
        buffer[length] = '\0';
        int n = (int)time(NULL);
        int timestamp = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; // get the timestamp from the message

        printf( "%dsd ago - %d bytes (4 bytes for timestamp): '%s'\n", n - timestamp, length, buffer+4 );
    }

    close( fd );
}

注意:信用:https://stackoverflow.com/a/35570418/3161139 用于 UDP 服务器/客户端“hello world”

NB2:请注意,您应该在发送消息之前计算时间戳并将其 memcpy 到缓冲区,而不是在循环之前,但希望您了解总体思路

NB3:正如 chux 建议的那样,您可以避免截断:

time_t n = time(NULL); 
int len = sizeof(n);
unsigned char timestamp[len];
// fill timestamp with n

...

memcpy(&buffer, &timestamp, len);
memcpy(&buffer[len], &s, strlen(s));

【讨论】:

  • 为什么用int n = (int)time(NULL);time_t 截断为int?可以使用time_t n = time(NULL);unsigned char timestamp[sizeof n];
  • 示例运行良好,非常感谢!另一件事,如果我在设置套接字时使用一些标志,例如 SOF_TIMESTAMPING_TX_HARDWARE 或其他东西,我可以获得时间戳,它可能由网络适配器生成,它准确记录了发送或接收数据包的时间。有什么方法可以将这个时间戳与我的数据一起从客户端发送到服务器,以便我可以获得更准确的时间戳?
  • 我不确定SOF_TIMESTAMPING_TX_HARDWARE,但我认为它在后台调用时间戳并执行我与您分享的相同类型。很高兴它有帮助!如果它解决了您的问题,您可以选择它作为答案!
猜你喜欢
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多