unp学习笔记之时间获取客户端(001)

unp源码获取与编译

  • 源码获取、解压流程如下:
wget http://www.unpbook.com/unpv13e.tar.gz
tar -zxvf unpv13e.tar.gz
  • 源码编译,建议先查看源码中的 README
# README 部分内容如下:
QUICK AND DIRTY
===============

Execute the following from the src/ directory:

    ./configure    # try to figure out all implementation differences

    cd lib         # build the basic library that all programs need
    make           # use "gmake" everywhere on BSD/OS systems

    cd ../libfree  # continue building the basic library
    make

    cd ../libroute # only if your system supports 4.4BSD style routing sockets
    make           # only if your system supports 4.4BSD style routing sockets

    cd ../libxti   # only if your system supports XTI
    make           # only if your system supports XTI

    cd ../intro    # build and test a basic client program
    make daytimetcpcli
    ./daytimetcpcli 127.0.0.1

If all that works, you're all set to start compiling individual programs.

Notice that all the source code assumes tabs every 4 columns, not 8.

MORE DETAILS
......
  • 按照源码流程编译
# 下面这两组命令一般不会出问题
cd unpv13e
./configure

cd lib
make

# 下面 make 可能会出现问题, 解决办法见 下方solve1
cd ../libfree
make

# libroute 一般不编译
cd ../libxti
make

# 通常可以直接 make 编译出可执行文件
cd ../intro
make daytimetcpcli

# 执行可能会出现 connect error: Connection refused
# 解决办法见 solve2
./daytimetcpcli 127.0.0.1
  • solve1
    错误提示的内容大概是:inet_ntop.c 中60行声明与原型申明 /usr/include/arpa/inet.h不匹配;
    解决方法:
    在 inet.h 中将 size_t 定义成 socklen_t,即在 /usr/include/arpa/inet.h 中添加下面这句话
// 添加在头文件之后
// inet.h为只读文件,需要sudo vim 或 sudo nano 才能修改
#define size_t socklen_t
  • solve2
    出现问题的原因可能是没安装 xinetd 或者 daytime 服务程序没开
# 安装 xinetd
sudo apt-get install xinetd

# 打开 daytime文件,将两个disable = yes 修改成 disable = no
vim /etc/xinetd.d/daytime
(修改...)

# 修改后许重启 xinetd 服务
service xinetd restart

时间获取客户端启动流程

程序的流程如下:

  1. 声明相关结构体、变量
  2. 创建网际字节流套接字
  3. 将工作类型、IP地址、端口号填入套接字(IP地址点分制转换成正确格式)
  4. 建立TCP连接
  5. 读取数据
  6. 输出数据

每个步骤的关键结构体、函数如下

step 1:		struct sockaddr_in
step 2:		socket(AF_INET, SOCKSTREAM, 0)
step 3:		htons(端口号)		//转换端口号
			inet_pto(AF_INET, 源字符串地址, 目的字符串地址)	//转换IP地址
step 4:		connect(sockfd, IP地址的地址, ip地址的长度)
step 5:		read(sockfd, 存放地址, 读取长度)
step 6:		fputs(存放地址, stdout)

时间获取客户端

#include <stdio.h>
#include <unp.h>

void err_log(int numb, char * s);

int
main(int argc, char *argv[]){
    /*声明变量、结构体*/
    int     sockfd, n;
    char    recvline[MAXLINE + 1];
    struct sockaddr_in  sadd;
    //struct hostent *    hp;
    
    /*判断系统输入参数*/
    if (argc != 2)
        err_log(-1, "usage: get_server_time <IPaddress>");

    /*socket创建一个网际(AF_INET) 字节流(SOCK_STREAM) 套接字*/
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        err_log(-2, "socket error");

    /*初始化结构体*/
    memset(&sadd, 0, sizeof(sadd));

    /*将服务器的工作类型、IP地址与端口号填入网际套接字*/
    sadd.sin_family     = AF_INET;
    sadd.sin_port       = htons(13);       // day time server
    if (inet_pton(AF_INET, argv[1], &sadd.sin_addr) <= 0)    // 将点分制ip转换成正确格式,递给 sockaddr_in 中的 sin_addr
        err_log(-1, "inet_pton error for this ip");

    /*build a TCP connect, and determine if the link is established*/
    if (0 > connect(sockfd, (struct sockaddr *)&sadd, sizeof(sadd)))
        err_log(-2, "connect error");

    /*read data*/
    while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = 0;    // end of string
        if (fputs(recvline, stdout) == EOF)
            err_log(-2, "fputs error");
    }
    if (n < 0)
        err_log(-2, "read error");
    
    exit(0);
}

// 重写一遍之后,err_sys err_exit函数无法使用
// 只好自己写了一个err_log函数替代
// 在大型项目中,可以在这个函数中将错误写入log
void 
err_log(int numb, char * s) {
    printf("%s\n", s);
    
    switch (numb)
    {
    case -1:
        exit(-1);
    case -2:
        exit(-2);
    default:
        exit(numb); 
    }
}

测试结果

# 大概会输出这种形式的字符串
22 MAY 2019 21:06:40 CST
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值