Linux 网络编程: xinetd time

前言

终于把 xinetd 服务装好了,那就在来实现一下 TCP 协议从服务器和本机获取时间吧。那么多思想汇报还没写,我也是醉了。

安装 xinetd

apt-get install xinetd

配置开启 time 服务

vi /etc/xinetd.d/time

disable = yes 改成 disable = no ,看注释很清楚 time 服务返回的是1900年1月1日到现在的秒数。如果没有写的权限,就要 chmod

chmod 777 time

重启 xinetd 服务

service xinetd restart

客户端

errexit.c

/* errexit.c - errexit */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

/*------------------------------------------------------------------------
 * errexit - print an error message and exit
 *------------------------------------------------------------------------
 */
int errexit(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    exit(1);
}

errno.h

/* Error constants.  Linux specific version.
   Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifdef _ERRNO_H

# undef EDOM
# undef EILSEQ
# undef ERANGE
# include <linux/errno.h>

/* Linux has no ENOTSUP error code.  */
# define ENOTSUP EOPNOTSUPP

/* Linux also had no ECANCELED error code.  Since it is not used here
   we define it to an invalid value.  */
# ifndef ECANCELED
#  define ECANCELED 125
# endif

# ifndef __ASSEMBLER__
/* Function to get address of global `errno' variable.  */
extern int *__errno_location (void) __THROW __attribute__ ((__const__));

#  if !defined _LIBC || defined _LIBC_REENTRANT
/* When using threads, errno is a per-thread value.  */
#   define errno (*__errno_location ())
#  endif
# endif /* !__ASSEMBLER__ */
#endif /* _ERRNO_H */

#if !defined _ERRNO_H && defined __need_Emath
/* This is ugly but the kernel header is not clean enough.  We must
   define only the values EDOM, EILSEQ and ERANGE in case __need_Emath is
   defined.  */
# define EDOM   33  /* Math argument out of domain of function.  */
# define EILSEQ 84  /* Illegal byte sequence.  */
# define ERANGE 34  /* Math result not representable.  */
#endif /* !_ERRNO_H && __need_Emath */

connectsock.c

/* connectsock.c - connectsock */
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif  /* INADDR_NONE */

extern int  errno;

int errexit(const char *format, ...);

/*------------------------------------------------------------------------
 * connectsock - allocate & connect a socket using TCP or UDP
 *------------------------------------------------------------------------
 */
int connectsock(const char *host, const char *service, const char *transport )
/*
 * Arguments:
 *      host      - name of host to which connection is desired
 *      service   - service associated with the desired port
 *      transport - name of transport protocol to use ("tcp" or "udp")
 */
{
    struct hostent  *phe;   /* pointer to host information entry    */
    struct servent  *pse;   /* pointer to service information entry */
    struct protoent *ppe;   /* pointer to protocol information entry*/
    struct sockaddr_in sin; /* an Internet endpoint address     */
    int s, type;    /* socket descriptor and socket type    */


    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;

    /* Map service name to port number */
    if ( pse = getservbyname(service, transport) )
        sin.sin_port = pse->s_port;
    else if ((sin.sin_port=htons((unsigned short)atoi(service))) == 0)
        errexit("can't get \"%s\" service entry\n", service);

    /* Map host name to IP address, allowing for dotted decimal */
    if ( phe = gethostbyname(host) )
        memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
    else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE )
        errexit("can't get \"%s\" host entry\n", host);

    /* Map transport protocol name to protocol number */
    if ( (ppe = getprotobyname(transport)) == 0)
        errexit("can't get \"%s\" protocol entry\n", transport);

    /* Use protocol to choose a socket type */
    if (strcmp(transport, "udp") == 0)
        type = SOCK_DGRAM;
    else
        type = SOCK_STREAM;

    /* Allocate a socket */
    s = socket(PF_INET, type, ppe->p_proto);
    if (s < 0)
        errexit("can't create socket: %s\n", strerror(errno));

    /* Connect the socket */
    if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        errexit("can't connect to %s.%s: %s\n", host, service,
            strerror(errno));
    return s;
}

connectTCP.c

/* connectTCP.c - connectTCP */

int connectsock(const char *host, const char *service,
        const char *transport);

/*------------------------------------------------------------------------
 * connectTCP - connect to a specified TCP service on a specified host
 *------------------------------------------------------------------------
 */
int connectTCP(const char *host, const char *service )
/*
 * Arguments:
 *      host    - name of host to which connection is desired
 *      service - service associated with the desired port
 */
{
    return connectsock( host, service, "tcp");
}

TCPtime.c

/* TCPtime.c - TCPtime, main */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include <time.h>

extern int      errno;

int     TCPtime(const char *host, const char *service);
int     errexit(const char *format, ...);
int     connectTCP(const char *host, const char *service);

#define LINELEN         128

/*------------------------------------------------------------------------
 * main - TCP client for DAYTIME service
 *------------------------------------------------------------------------
 */
int main(int argc, char *argv[])
{
        char    *host1 = "localhost";    /* host to use if none supplied */
        char    *host2 = "localhost";    /* host to use if none supplied */

        switch (argc) {
        case 1:
                host1 = "localhost";
                host2 = "localhost";
                break;
        case 2:
                host2 = argv[1];
                break;
        default:
                fprintf(stderr, "The number of parameter is to much! Just need the other host~\n");
                exit(1);
        }
        TCPtime(host1, host2);
        exit(0);
}

/*------------------------------------------------------------------------
 * TCPtime - invoke Daytime on specified host and print results
 *------------------------------------------------------------------------
 */
int TCPtime(const char *host1, const char *host2)
{
    char    buf[LINELEN+1];         /* buffer for one line of text  */
    int     s1, s2, n;              /* socket, read count           */
    
    time_t  time1, time2;

    s1 = connectTCP(host1, "time");
    s2 = connectTCP(host2, "time");
    
    while( (n = read(s1, (char *)&time1, sizeof(time1))) > 0) {
        time1 = ntohl((unsigned long)time1);
        time1 -= 2208988800UL;
        time1 += 4294967296UL;
        printf("time in %s is %s", host1, ctime(&time1));
    }
    
    while( (n = read(s2, (char *)&time2, sizeof(time2))) > 0) {
        time2 = ntohl((unsigned long long)time2);
        time2 -= 2208988800UL;
        time2 += 4294967296UL;
        printf("time in %s is %s", host2, ctime(&time2));
    }
    printf("the difference is %d seconds.\n", abs(time1 - time2));
    return 0;
}

time_t 类型的长度在32位机器下是32位,在64位机器下是64位,所以在减去 2208988800UL 秒(变成1970年到现在的秒数)后,还要加上2的32次方秒。(我觉得如果能自己实现64位数的网络序转主机序应该也是可以实现的)。

编译运行

613086-20151027152652685-1682097345.png

转载于:https://www.cnblogs.com/pengzhendong/p/4914377.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值