1.通过tcp从daytime服务器获取时间

最近愈发觉得在学习源代码或者看书的时候,做下读书笔记,不仅能加深印象和理解,同时也方便日后进行回顾,所以就写下UNP(UNIX网络编程)卷1的读书笔记,涉及到的代码基本都是原作者提供的,为了方便编译做了一定简化,我是在Ubuntu上进行编译的,不同操作系统可能存在兼容问题。


该书第一个小程序就是通过tcp从daytime服务器获取时间,代码如下:

运行时传递一个daytime服务器的ip地址即可,大家可以在自己的服务器上运行daytime服务进行测试

#include 
#include 
#include 
#include 
#include 
#include 

#define MAXLINE 4096

void err_quit(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    
    char buf[MAXLINE + 1];
    vsnprintf(buf, MAXLINE, fmt, ap);
    strcat(buf, "\n");
    
    fflush(stdout);
    fputs(buf, stderr);
    fflush(stderr);

    exit(1);
}

int main(int argc, char **argv)
{
    int sockfd, n;
    char recvline[MAXLINE + 1];
    struct sockaddr_in servaddr;

    // 该程序需要接收1个参数, 该参数为daytime服务器的IP地址
    // 为什么是2呢? 命令行运行程序时, 程序的索引为0的参数就是程序名称
    if (argc != 2)
        err_quit("Usage: a.out ");

    // socket函数创建了一个网际(AF_INET)字节流(SOCK_STREAM)套接字, 它是TCP套接字的花哨名称;
    // 该函数会返回一个小整数描述符
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        err_quit("socket error");

    // 置servaddr结构体的所有字节为0, 可以使用memset替代
    bzero(&servaddr, sizeof(servaddr));
    // 置地址族为AF_INET
    servaddr.sin_family = AF_INET;
    // 置端口号为13, 这是daytime协议的默认端口号
    servaddr.sin_port = htons(13);
    // 置IP地址为第一个命令行参数
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) < 0)
        err_quit("inet_pton error for %s", argv[1]);

    // connect函数与套接字地址结构指定的服务器建立一个TCP连接
    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        err_quit("connect error");

    // read函数读取服务器的应答, 并使用fputs输出到标准输出, 可以使用printf进行替换
    // 由于TCP是一个没有记录边界的字节流协议, 我们无法确定何时能读取完全部数据, 所以这里使用循环来
    // 进行读取, 直至read返回0(表明对端关闭连接)或者负值(表明发生错误)时终止循环
    while ((n =read(sockfd, recvline, MAXLINE)) > 0)
    {
        recvline[n] = '\0';
        if (fputs(recvline, stdout) == EOF)
            err_quit("fputs error");
    }
    if (n < 0)
        err_quit("read error");

    exit(0);
}


你可能感兴趣的:(UNP卷1读书笔记)