最近愈发觉得在学习源代码或者看书的时候,做下读书笔记,不仅能加深印象和理解,同时也方便日后进行回顾,所以就写下UNP(UNIX网络编程)卷1的读书笔记,涉及到的代码基本都是原作者提供的,为了方便编译做了一定简化,我是在Ubuntu上进行编译的,不同操作系统可能存在兼容问题。
该书第一个小程序就是通过tcp从daytime服务器获取时间,代码如下:
运行时传递一个daytime服务器的ip地址即可,大家可以在自己的服务器上运行daytime服务进行测试
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#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 <IPaddress>");
// 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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)