17.UNP第一章 简介
获取时间的客户端代码:
1 //客户端程序 2 #include "unp.h" 3 4 int main(int argc, char **argv) 5 { 6 int sockfd, n; 7 char recvline[MAXLINE + 1]; 8 struct sockaddr_in servaddr; 9 //在ipv6可以运行: 10 //struct sockaddr_in6 servaddr; 11 12 if (argc != 2) 13 err_quit("usage: a.out <IPaddress>"); 14 15 //创建TCP套接字,AF_INET表示网际,SOCK_STREAM表示字节流 16 if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 17 err_sys("socket error"); 18 //ipv6 if ( (sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) 19 20 //结构体清零 21 bzero(&servaddr, sizeof(servaddr)); 22 //设置协议族 23 servaddr.sin_family = AF_INET; 24 //ipv6 servaddr.sin6_family = AF_INET6; 25 //设置端口号 26 servaddr.sin_port = htons(8888); /* daytime server */ 27 //ipv6 servaddr.sin6_port = htons(8888); 28 //把输入的点分十进制转换为合适的格式 29 if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) 30 //ipv6 if (inet_pton(AF_INET6, argv[1], &servaddr.sin_addr) <= 0) 31 err_quit("inet_pton error for %s", argv[1]); 32 33 //与指定的服务器建立一个TCP连接 34 //为了简化,把struct sockaddr宏定义为SA 35 if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) 36 err_sys("connect error"); 37 38 //读服务器的应答,并用标准的I/O函数fputs输出结果. 39 while ( (n = read(sockfd, recvline, MAXLINE)) > 0) { 40 recvline[n] = 0; /* null terminate */ 41 if (fputs(recvline, stdout) == EOF) 42 err_sys("fputs error"); 43 } 44 if (n < 0) 45 err_sys("read error"); 46 47 //终止程序 48 exit(0); 49 }
获取时间的服务器代码:
1 #include "unp.h" 2 #include <time.h> 3 4 int main() 5 { 6 int listenfd,connfd; 7 struct sockaddr_in servaddr; 8 char buff[MAXLINE]; 9 time_t ticks; 10 11 listenfd = Socket(AF_INET,SOCK_STREAM,0); 12 13 bzero(&servaddr,sizeof(servaddr)); 14 servaddr.sin_family = AF_INET; 15 //指定IP地址为INADDR_ANY的原因是如果服务器主机有多个网络接口, 16 //服务器进程就可以在任意网络接口上接受客户连接. 17 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 18 //设置端口号 19 servaddr.sin_port = htons(8888); 20 21 Bind(listenfd,(SA *)&servaddr,sizeof(servaddr)); 22 23 //把该套接字转换成一个监听套接字,这样来自客户的外来连接就可以在该 24 //套接字上由内核接收.LISTENQ在unp.h头文件中定义,用来指定系统内核允许在这个监听 25 //描述符上排队的最大客户连接数. 26 Listen(listenfd,LISTENQ); 27 28 for(;;) 29 { 30 //阻塞睡眠模式,三次握手,握手完毕后,accept返回 31 //返回值是一个已连接描述符,该描述符用于与连接的那个客户通信. 32 connfd = Accept(listenfd,(SA *)NULL,NULL); 33 34 //获得当前时间 35 ticks = time(NULL); 36 37 //ctime可以把该整数值转换为时间的模式 38 //snprintf第二个参数指定缓冲区的大小,可以确保该缓冲区不溢出 39 //为了避免黑客的溢出攻击,最好把使用的函数比如(gets,strcat,strcpy)改为 40 //fgets,strncat,strncpy 41 snprintf(buff,sizeof(buff),"%.24s\r\n",ctime(&ticks)); 42 Write(connfd,buff,strlen(buff)); 43 44 //终止连接 45 close(connfd); 46 } 47 return 0; 48 }