【问题标题】:xinetd server return value is not readable [closed]xinetd 服务器返回值不可读[关闭]
【发布时间】:2021-02-24 00:46:10
【问题描述】:

我已经启用了所有的 xinetd 服务,我正在从 c 程序调用它。一切正常,但是当我调用时间服务时,它返回不可读的 4 字节值。以下是一个示例输出。

那么,如何将此输出转换为可读格式?

【问题讨论】:

  • 最好转到 Unix 和 Linux 站点。

标签: c linux sockets xinetd


【解决方案1】:

根据Wikipedia

然后服务器将时间作为 32 位无符号整数以二进制格式和网络字节顺序发送,表示自格林威治标准时间 1900 年 1 月 1 日 00:00(午夜)起的秒数,并关闭连接。

解码为本机字节顺序(通过ntohl() 或朋友)后,您可以使用该值做您喜欢的事情。请注意,它不适用于采用 time_t 之类的 ctime() 的函数,因为正常的 Unix 纪元(0 点)是不同的日期。幸运的是,这可以通过从提供的时间中减去时间协议的 0 点的纪元偏移量来解决。


这是一个示例程序,它连接到作为其唯一命令行参数传递的给定 IP 地址或主机名的时间服务,并打印出接收到的值和人类可读的日期字符串(使用上述偏移量转换为一个正常的 Unix 时间值):

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

// 00:00  1 Jan 1970 GMT in RFC 868 time format.
#define EPOCH_OFFSET 2208988800U

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Usage: %s hostname\n", argv[0]);
    return EXIT_FAILURE;
  }

  struct addrinfo *res;
  struct addrinfo hints = {
    .ai_family = AF_UNSPEC,
    .ai_socktype = SOCK_STREAM
  };
  int err;

  if ((err = getaddrinfo(argv[1], "time", &hints, &res)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
    return EXIT_FAILURE;
  }

  for (struct addrinfo *addr = res; addr; addr = addr->ai_next) {
    int s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
    if (s >= 0) {
      if (connect(s, addr->ai_addr, addr->ai_addrlen) == 0) {
        uint32_t raw;
        if (read(s, &raw, sizeof raw) != sizeof raw) {
          fprintf(stderr, "Could not read complete time.\n");
          close(s);
          freeaddrinfo(res);
          return EXIT_FAILURE;
        }
        raw = ntohl(raw);
        printf("Got raw time: %" PRIu32 "\n", raw);

        time_t tval = raw - EPOCH_OFFSET;
        printf("Converted time: %s", ctime(&tval));

        close(s);
        freeaddrinfo(res);
        return 0;
      } else {
        close(s);
      }
    }
  }
  
  printf("Unable to connect to %s's time server.\n", argv[1]);
  freeaddrinfo(res);
  return EXIT_FAILURE;
}

【讨论】:

  • 有趣的是,原始的RFC 868 没有说明字节顺序或签名性——它甚至有一个负时间的例子(但请参阅errata 关于那个)。跨度>
猜你喜欢
  • 2014-03-05
  • 1970-01-01
  • 2015-06-22
  • 2019-02-18
  • 1970-01-01
  • 2012-08-15
  • 1970-01-01
  • 2014-06-27
  • 2016-02-12
相关资源
最近更新 更多