在读取here的同时,HERHE和HERHE我看到,在Linux系统上,您可以通过设置套接字选项从接收和发送的数据包中请求时间戳。我目前可以使用SO_TIMESTAMPNS
和
SO_TIMESTAMPING
来获得带有recvmsg
的RX时间戳。使用sendmsg
我不知道如何正确打包控制消息的辅助数据,而sendmsg甚至没有可以持有我需要的数据的返回。
这就是我如何获得RX时间戳。
import socket
SO_TIMESTAMPING = 37
SOF_TIMESTAMPING = 127
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPING, SO_TIMESTAMPING, SOF_TIMESTAMPING)
server_sock.bind((_svr_ip, _svr_port))
server_sock.listen(_num_clients)
conn, client_addr = server_sock.accept()
msg, ancdata, flags, address = conn.recvmsg(64, 1024)
t_rx = ancdata[0][2]
t_rx_s = int.from_bytes(t_rec[0:7], byteorder="little")
t_rx_ns = int.from_bytes(t_rec[8:], byteorder="little")
节1.3.4提及通过控制消息启用时间戳,而无需使用
socket.setsockopt
保留开销。我相信这意味着您在调用sendmsg
而不是使用
socket.setsockopt
.时将标志添加到控制消息中。您已经看到,sendmsg()中没有字段可以返回时间戳。 无论如何,这都是不切实际的。 sendmsg()仅将数据包排队到内核插座缓冲区。 仅当数据包实际发送时,TX时间戳才会生成。 对于硬件时间戳,实际上是由NIC生成的,当数据包在电线上熄灭时。 INSTEAD,TX时间戳发生的事情是将时间戳添加到插座“错误队列”中。错误队列是异步的辅助数据的通道。 这可能是一个网络错误,但即使不是错误,也用于时间戳。
recvmsg
设置
MSG_ERRQUEUE
。 此调用将
not返回任何实际的套接字数据。 取而代之的是,它返回传输数据包的副本,以及包含时间戳的固有数据字段。 您可以在使用
SOF_TIMESTAMPING_OPT_TSONLY
时使用setsockopt
选项来抑制包含传输数据包的副本。
如果我修改您的示例以使用TXTimestamps
import socket
SO_TIMESTAMPING = 37
SOF_TIMESTAMPING = 127
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_sock.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPING, SOF_TIMESTAMPING)
server_sock.bind((_svr_ip, _svr_port))
server_sock.listen(_num_clients)
conn, client_addr = server_sock.accept()
conn.send(b"hello, world")
msg, ancdata, flags, address = conn.recvmsg(64, 1024, socket.MSG_ERRQUEUE)
for layer, opt, data in ancdata:
if layer == socket.SOL_SOCKET and opt == sol.SO_TIMESTAMPING:
t_send = data
t_tx_s = int.from_bytes(t_send[0:7], byteorder="little")
t_tx_ns = int.from_bytes(t_send[8:], byteorder="little")
print(f"packet sent time: {t_tx_s}.{t_tx_ns:09}")
可以通过使用辅助数据更改每个调用的时间戳选项。 它应该看起来像这样:
SOF_TIMESTAMPING_TX_SOFTWARE = 2
opt_bytes = SOF_TIMESTAMPING_TX_SOFTWARE.to_bytes(4, 'little')
conn.sendmsg([b'hello, world], [(socket.SOL_SOCKET, SO_TIMESTAMPING, opt_bytes)])
msg, ancdata, flags, address = conn.recvmsg(64, 1024, socket.MSG_ERRQUEUE)
我知道,您需要通常使用setSockopt启用的时间戳,但是您可以省略sof_timestamping_tx_software lit,然后将其应用于show的辅助数据。