Próbuję wysłać znacznik transmisji pakietu, aby obliczyć opóźnienie. Dzięki Linux, Datagramów UDP i znaczniki czasu jądra: wiele przykładów i wpisów stacjonarnych przepływów później i nadal ...

-1
gtyss 26 marzec 2021, 06:32

1 odpowiedź

Najlepsza odpowiedź

Musisz przechowywać bajty czasu znacznika w wiadomości (na początku jest najlepiej, w swoim własnym nagłówku, wraz z innymi ważnymi informacjami). Zobacz przykład poniżej:

Klient

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

Serwer

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

NB: Kredyt: https://stackoverflow.com/a/35570418/3161139 dla serwera UDP / klienta " Hello World "

NB2: Zauważ, że należy obliczyć znacznik czasu i memcpy do bufora tuż przed wysłaniem wiadomości, a nie przed pętlą, ale miejmy nadzieję, że otrzymasz ogólne pomysł

NB3: Ponieważ Chux sugeruje, że można uniknąć obcięcia:

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));
0
Antonin GAVREL 26 marzec 2021, 06:25