如何将传输时间戳与数据有效载荷一起发送?

How to send transmit timestamps along with data payload?

我正在尝试发送数据包的传输时间戳来计算延迟。感谢 , I can get timestamp when datagrams are sent and received. However, the demo in this entry can only get the transmit timestamp in sender and get the receive timestamp in receiver. I wonder that how can I send datagrams along with the transmit timestamp so that I can get both transmit and receive timestamps in receiver? I have read the https://www.kernel.org/doc/Documentation/networking/timestamping.txt 文档,但我没有找到可能有帮助的东西。任何人都可以对此有想法吗?

谢谢!

您必须在消息中存储时间戳的字节(开头最好,在您自己的 header 理想情况下,连同其他重要信息)。请参见下面的示例:

客户

#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[=10=]";
    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] = '[=11=]';
        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://whosebug.com/a/35570418/3161139 用于 UDP server/client“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));