该程序是TCP当前时间查询客户端程序的实现。客户端与其服务器端建立一个TCP连接后,服务器返回当前时间和日期。
1 // client 2 #include "unp.h" 3 int main(int argc, char **argv) { 4 int sockfd, n; 5 char recvline[MAXLINE+1]; 6 7 /* 8 * struct sockaddr_in{ 9 * unsigned short sin_family; //一般为AF_INET 10 * unsigned short int sin_port; //监听的端口号 11 * struct in_addr sin_addr; //设置为INADDR_ANY,表示可以和任何主机通信 12 * unsigned char sin_zero[8]; //用来填充的 13 * } 14 */ 15 struct sockaddr_in servaddr; 16 17 if(argc != 2) { 18 err_quit("usage: a.out <IPaddress>"); 19 } 20 21 /* 22 * socket 23 * int socket(int domain, int type, int protocol) 24 * domain: 25 * AF_UNIX只能够用于单一的UNIX进程间通信 26 * AF_INET用于Internet通信,允许在远程主机间的通信 27 * type: 28 * SOCK_STREAM表明我们用的TCP协议,这样是提供按顺序,可靠的,双向的,面向连接的比特流。 29 * SOCK_DGRAM表明我们用的是UDP协议,提供定长的,不可靠的,无连接的通信. 30 * protocol: 31 * 由于指定了type,这个地方我们用0代替 32 * sockfd: 33 * 成功时返回的文件标识符,失败时返回-1 34 */ 35 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 36 err_sys("socket error"); 37 } 38 39 //结构体清零 40 bzero(&servaddr, sizeof(servaddr)); 41 servaddr.sin_family = AF_INET; //IPv4地址族,AF_INET6为IPv6地址族 42 servaddr.sin_port = htons(13); //设置端口号为13 43 /* 44 * inet_pton:将“点分十进制” -> “二进制整数” 45 * int inet_pton(int af, const char *src, void *dst); 46 * af:地址族 47 * *src: 点分十进制地址 48 * *dst: 要转换的二进制整数 49 */ 50 if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { 51 err_quit("inet_pton error for %s", argv[1]); 52 } 53 54 /* 55 * connect函数是客户端用来与服务器端连接的,成功时返回0,失败时返回-1 56 * int connect(int sockfd, struct sockaddr * serv_addr,int addrlen) 57 * sockfd: 58 * 创建socket时返回的文件描述符 59 * serv_addr: 60 * 储存了服务器端的连接信息,其中sin_addr服务器是服务器端的地址 61 * addrlen: serv_addr的长度 62 */ 63 64 if(connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) < 0) { 65 err_sys("connect error"); 66 } 67 68 //read()函数读取服务器的应答,并用标准的I/O函数fputs输出结果 69 //read()一般编写到某个循环中,返回0(表明关闭连接)或负值(表明发生错误) 70 while( (n = read(sockfd, recvline, MAXLINE)) > 0) { 71 recvline[n] = 0; 72 if(fputs(recvline, stdout) == EOF) { 73 err_sys("fputs error"); 74 } 75 } 76 if(n < 0) { 77 err_sys("read error"); 78 } 79 return 0; 80 }