前言

如果你这段时间过得很舒服,那就证明你荒废以一段时间。如果你这段时间过得很辛苦,那么恭喜,你又进步了。最近入党的事情忙得焦头烂额,博客也拖了好久没写,主要也是因为要装 xinetd 服务一直没装好,Mac 上也无法编译多个文件,于是我还特意租了一个月服务器。OK,现在来实现客户端链接主机,从主机获取时间。

Error

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 */

Server

passivesock.c

/* passivesock.c - passivesock */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
extern int errno; int errexit(const char *format, ...); unsigned short portbase = 0; /* port base, for non-root servers */ /*------------------------------------------------------------------------
* passivesock - allocate & bind a server socket using TCP or UDP
*------------------------------------------------------------------------
*/
int passivesock(const char *service, const char *transport, int qlen)
/*
* Arguments:
* service - service associated with the desired port
* transport - transport protocol to use ("tcp" or "udp")
* qlen - maximum server request queue length
*/
{
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;
sin.sin_addr.s_addr = INADDR_ANY; /* Map service name to port number */
if ( pse = getservbyname(service, transport) )
sin.sin_port = htons(ntohs((unsigned short)pse->s_port)
+ portbase);
else if ((sin.sin_port=htons((unsigned short)atoi(service))) == 0)
errexit("can't get \"%s\" service entry\n", service); /* Map 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)); /* Bind the socket */
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
errexit("can't bind to %s port: %s\n", service,
strerror(errno));
if (type == SOCK_STREAM && listen(s, qlen) < 0)
errexit("can't listen on %s port: %s\n", service,
strerror(errno));
return s;
}

passiveTCP.c

/* passiveTCP.c - passiveTCP */

int	passivesock(const char *service, const char *transport,
int qlen); /*------------------------------------------------------------------------
* passiveTCP - create a passive socket for use in a TCP server
*------------------------------------------------------------------------
*/
int passiveTCP(const char *service, int qlen)
/*
* Arguments:
* service - service associated with the desired port
* qlen - maximum server request queue length
*/
{
return passivesock(service, "tcp", qlen);
}

TCPdaytimed.c

/* TCPdaytimed.c - main */
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
extern int errno;
int errexit(const char *format, ...);
void TCPdaytimed(int fd);
int passiveTCP(const char *service, int qlen); #define QLEN 32 /*------------------------------------------------------------------------
* main - Iterative TCP server for DAYTIME service
*------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
struct sockaddr_in fsin; /* the from address of a client */
char *service = "daytime"; /* service name or port number */
int msock, ssock; /* master & slave sockets */
unsigned int alen; /* from-address length */ switch (argc) {
case 1:
break;
case 2:
service = argv[1];
break;
default:
errexit("usage: TCPdaytimed [port]\n");
} msock = passiveTCP(service, QLEN); while (1) {
alen = sizeof(fsin);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if (ssock < 0)
errexit("accept failed: %s\n", strerror(errno));
TCPdaytimed(ssock);
(void) close(ssock);
}
} /*------------------------------------------------------------------------
* TCPdaytimed - do TCP DAYTIME protocol
*------------------------------------------------------------------------
*/
void TCPdaytimed(int fd)
{
char *pts; /* pointer to time string */
time_t now; /* current time */
char *ctime(); (void) time(&now);
pts = ctime(&now);
(void) write(fd, pts, strlen(pts));
}

客户端链接服务器时,服务器获取时间然后将获取到的秒数通过 ctime() 函数转换成标准格式返回给客户端。

Client

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");
}

TCPdaytime.c

/* TCPdaytime.c - TCPdaytime, main */
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include <time.h> extern int errno; int TCPdaytime(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);
}
TCPdaytime(host1, host2);
exit(0);
} /*------------------------------------------------------------------------
* TCPdaytime - invoke Daytime on specified host and print results
*------------------------------------------------------------------------
*/
int TCPdaytime(const char *host1, const char *host2)
{
char buf[LINELEN+1]; /* buffer for one line of text */
int s1, s2, n; /* socket, read count */
struct tm time1, time2;
long second1, second2; s1 = connectTCP(host1, "daytime");
s2 = connectTCP(host2, "daytime"); while( (n = read(s1, buf, LINELEN)) > 0) {
buf[n] = '\0'; /* ensure null-terminated */
strptime(buf, "%a %b %d %H:%M:%S %Y", &time1);
printf("time in localhost is\t");
(void) fputs( buf, stdout );
} while( (n = read(s2, buf, LINELEN)) > 0) {
buf[n] = '\0'; /* ensure null-terminated */
strptime(buf, "%a %b %d %H:%M:%S %Y", &time2);
printf("time in %s is\t", host2);
(void) fputs( buf, stdout );
/*stdout是一个文件指针,C己经在头文件中定义好的了,可以直接使用,把它
赋给另一个文件指针。只是方便操作输出,比如传给一个函数等等。这时函数
的输出就不是输出到文件,而是传进来的stdout文件指针,即标准输出。*/
} second1 = mktime(&time1);
second2 = mktime(&time2); printf("time difference is %d seconds.\n", abs(second1-second2)); return 0;
}

默认连接的两个主机都是 localhost ,如果输入主机地址,则同时连接 localhost 和目标主机,获取到两台主机的时间。为了比较两台主机之间的时间差,一开始我想着服务器直接返回秒数,但是要转换成字符串才能返回就放弃了。通过 strptime()按照特定时间格式将字符串转换为时间类型,然后通过 mktime()将时间转换为自1970年1月1日以来持续时间的秒数,这样就可以进行运算了。

编译运行

编译运行 server:

将 server 上传到服务器:

连接服务器开启服务:

开启客户端,分别只连接 localhost 和同时连接两台服务器:

Linux 网络编程: daytime Service的更多相关文章

  1. Linux 网络编程: echo Service

    前言 大病初愈,感谢某人的陪伴,感谢王乐庆同学和赵攀同学的细心照顾.原以为过了第八周就不忙了,却没想到还有明天的党章考试.还是写代码比背党章有意思~趁着服务器还没过期,赶紧把 echo 完成了.关于错 ...

  2. 第5章 Linux网络编程基础

    第5章 Linux网络编程基础 5.1 socket地址与API 一.理解字节序 主机字节序一般为小端字节序.网络字节序一般为大端字节序.当格式化的数据在两台使用了不同字节序的主机之间直接传递时,接收 ...

  3. Linux网络编程基础API

    第5章 Linux网络编程基础API 探讨Linux网络编程基础API与内核中TCP/IP协议族之间的关系,并未后续章节提供编程基础.从3个方面讨论Linux网络API. socket地址API.so ...

  4. 【linux草鞋应用编程系列】_5_ Linux网络编程

    一.网络通信简介   第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章.   二.linux网络通信     在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...

  5. linux网络编程 no route to host 解决方案

    linux网络编程 no route to host 解决方案 [整合资料] (2013-05-13 21:38:12) 转载▼ 标签: net iptables it 分类: Linux 参考资料h ...

  6. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  7. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  8. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  9. 《转》Linux网络编程入门

    原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...

随机推荐

  1. oracle sql命令行中上下左右使用

    yum -y install readline,rlwrap

  2. asp.net弹出多个模态窗口

    asp.net中无限制弹出模态窗口 特点: 1.       可以在模态窗口上再弹出模态窗口,不限制次数 2.       弹出窗口的支持拖放,及调整大小 3.       弹出窗口关闭后可以动态控制 ...

  3. 不要再坑人啦!NSOperation才是苹果推荐使用的多线程技术!

    首先声明一下.小汤我在实际开发中呢,实际上也是喜欢用GCD多一点,由于用起来感觉更方便. 可是,事实是什么呢? 苹果推荐使用的实际上是NSOperation.所以希望对此没有研究的各位不要再在博客中误 ...

  4. JavaScript引用类型之Object类型

    在JavaScript中大多数的引用类型都是Object的实例,Object类型也是使用最多的类型! 创建Object类型实例的方式有两种,下面分别来分析一下: (1)第一种是使用new操作符后跟Ob ...

  5. JavaSE思维导图(一)

  6. Android App开发常用专题开源代码

    Android App开发中用到过的专题类开源代码: 项目的需求多了,不知不觉成了Github摘抄员,感谢分享精神,节省了很多弯路和时间.不过想要实现指定效果,还是要看懂作者的思路才好下手改造. 主题 ...

  7. Easyui + jQuery表单提交 给 Controller patr1

    2014-11-15  总结上周在公司开发所用到的技术,由于是刚找的工作(一个大三实习生)+自己的技术菜,有很多地方都是怎么想就怎么实现的, 如果你有什么更好的解决方法,在看见这篇博客的时候,希望你能 ...

  8. Socket缓冲区探讨,是否有拆包的方式?

    Socket缓冲区探讨 本文主要探讨java网络套接字传输模型,并对如何将NIO应用于服务端,提高服务端的运行能力和降低服务负载. 1.1 socket套接字缓冲区 Java提供了便捷的网络编程模式, ...

  9. uva 10779 Collectors Problem 网络流

    链接 一共有n个人, m种收藏品, 每个人拥有的收藏品的种类和个数都是不相同的. 假设2-n这些人都只和1互相交换, 比例是1:1, 并且, 2-n这些人, 只换自己现在没有的, 如果他现在有第二种, ...

  10. python 利用位移法将ip转为number以及将number转为ip

    简介: 使用位移法将ip转为number型以及将number型转为ip,使用语言为python2.7 #!/usr/bin/env python # coding:utf-8 def ip2num(i ...