如何将传输时间戳与数据有效载荷一起发送?
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, ×tamp, 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, ×tamp, len);
memcpy(&buffer[len], &s, strlen(s));
我正在尝试发送数据包的传输时间戳来计算延迟。感谢
谢谢!
您必须在消息中存储时间戳的字节(开头最好,在您自己的 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, ×tamp, 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, ×tamp, len);
memcpy(&buffer[len], &s, strlen(s));