#sntp #async #networking #time #system-clock

rsntp

一个符合RFC 5905的Rust简单网络时间协议(SNTP)客户端库

15个版本 (稳定)

4.0.0 2024年1月31日
3.0.2 2023年3月19日
3.0.1 2022年5月1日
3.0.0 2022年2月22日
0.1.0 2019年12月29日

#1 in #system-clock

Download history 2920/week @ 2024-04-14 2396/week @ 2024-04-21 2887/week @ 2024-04-28 1879/week @ 2024-05-05 2189/week @ 2024-05-12 4154/week @ 2024-05-19 3963/week @ 2024-05-26 3952/week @ 2024-06-02 3814/week @ 2024-06-09 3592/week @ 2024-06-16 2967/week @ 2024-06-23 2227/week @ 2024-06-30 4766/week @ 2024-07-07 3950/week @ 2024-07-14 3312/week @ 2024-07-21 4237/week @ 2024-07-28

每月下载量16,347
用于 4 crates

MIT/Apache

83KB
1.5K SLoC

CircleCI

rsntp

一个符合RFC 5905的Rust简单网络时间协议(SNTP)客户端库。

rsntp提供了一个API,用于与SNTPv4时间服务器同步时间,具有以下特性

  • 提供同步(阻塞)和异步(可选)API,基于tokio
  • 可选支持时间日期库chronotime(默认启用chrono
  • 支持IPv6

使用方法

将以下内容添加到您的Cargo.toml

[dependencies]
rsntp = "4.0.0"

使用阻塞API获取当前本地时间

use rsntp::SntpClient;
use chrono::{DateTime, Local};

let client = SntpClient::new();
let result = client.synchronize("pool.ntp.org").unwrap();

let local_time: DateTime<Local> =
  DateTime::from(result.datetime().into_chrono_datetime().unwrap());

println!("Current time is: {}", local_time);

您还可以使用异步API执行相同操作

use rsntp::AsyncSntpClient;
use chrono::{DateTime, Local, Utc};

async fn local_time() -> DateTime<Local> {
  let client = AsyncSntpClient::new();
  let result = client.synchronize("pool.ntp.org").await.unwrap();
   
   DateTime::from(result.datetime().into_chrono_datetime().unwrap())
}

3.0版本中的API更改

3.0版本使核心代码与时间日期库独立,并添加了对time库的支持。这导致一些API的重大更改,SynchronizationResult方法将使用包装结构而不是chrono结构返回。这些包装结构具有TryInto实现以及将它们转换为chrono格式的辅助方法。

要将旧代码进行转换,替换

let datetime = result.datetime();

let datetime = result.datetime().into_chrono_datetime().unwrap();

let datetime: chrono::DateTime<Utc> = result.datetime().try_into().unwrap();

同样的方法也适用于由SynchronizationResult返回的Duration

对时间日期库的支持

rsntp支持以不同格式返回时间和日期数据。目前支持两种最流行的日期和时间处理库的格式:chronotime。默认情况下,启用chrono,但您可以通过功能添加对time的支持

use rsntp::SntpClient;

let client = SntpClient::new();
let result = client.synchronize("pool.ntp.org").unwrap();

let utc_time = result
  .datetime()
  .into_offset_date_time()
  .unwrap();

println!("UTC time is: {}", utc_time);

可以独立启用两个库的支持;您甚至可以同时启用两个库。

禁用异步API

默认情况下启用异步API,但您可以禁用它。禁用的优点是它消除了对tokio的依赖,这大大减少了依赖项的数量。

[dependencies]
rsntp = { version = "4.0.0", default-features = false, features = ["chrono"] }

系统时钟假设

rsntp 假设系统时钟是单调且稳定的。这对于 SynchronizationResult::datetime() 方法尤为重要,因为 SynchronizationResult 只存储系统时钟的偏移量。如果系统时钟在同步和调用此方法之间发生变化,则偏移量将不再有效,并返回一些未定义的结果。

支持IPv6

rsntp 支持IPv6,但由于兼容性原因,它默认将其UDP套接字绑定到IPv4地址(0.0.0.0)。这可能会阻止与IPv6服务器的同步。

要使用IPv6,您需要设置IPv6绑定地址

use rsntp::{Config, SntpClient};
use std::net::Ipv6Addr;

let config = Config::default().bind_address((Ipv6Addr::UNSPECIFIED, 0).into());
let client = SntpClient::with_config(config);

let result = client.synchronize("2.pool.ntp.org").unwrap();

let unix_timestamp_utc = result.datetime().unix_timestamp();

依赖关系

~1–9.5MB
~76K SLoC