该程序是TCP当前时间查询客户端程序的实现。客户端与其服务器端建立一个TCP连接后,服务器返回当前时间和日期。
// client
#include "unp.h"
int main(int argc, char **argv) {
int sockfd, n;
char recvline[MAXLINE+1];
/*
* struct sockaddr_in{
* unsigned short sin_family; //一般为AF_INET
* unsigned short int sin_port; //监听的端口号
* struct in_addr sin_addr; //设置为INADDR_ANY,表示可以和任何主机通信
* unsigned char sin_zero[8]; //用来填充的
* }
*/
struct sockaddr_in servaddr;
if(argc != 2) {
err_quit("usage: a.out <IPaddress>");
}
/*
* socket
* int socket(int domain, int type, int protocol)
* domain:
* AF_UNIX只能够用于单一的UNIX进程间通信
* AF_INET用于Internet通信,允许在远程主机间的通信
* type:
* SOCK_STREAM表明我们用的TCP协议,这样是提供按顺序,可靠的,双向的,面向连接的比特流。
* SOCK_DGRAM表明我们用的是UDP协议,提供定长的,不可靠的,无连接的通信.
* protocol:
* 由于指定了type,这个地方我们用0代替
* sockfd:
* 成功时返回的文件标识符,失败时返回-1
*/
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
err_sys("socket error");
}
//结构体清零
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET; //IPv4地址族,AF_INET6为IPv6地址族
servaddr.sin_port = htons(13); //设置端口号为13
/*
* inet_pton:将“点分十进制” -> “二进制整数”
* int inet_pton(int af, const char *src, void *dst);
* af:地址族
* *src: 点分十进制地址
* *dst: 要转换的二进制整数
*/
if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
err_quit("inet_pton error for %s", argv[1]);
}
/*
* connect函数是客户端用来与服务器端连接的,成功时返回0,失败时返回-1
* int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)
* sockfd:
* 创建socket时返回的文件描述符
* serv_addr:
* 储存了服务器端的连接信息,其中sin_addr服务器是服务器端的地址
* addrlen: serv_addr的长度
*/
if(connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) < 0) {
err_sys("connect error");
}
//read()函数读取服务器的应答,并用标准的I/O函数fputs输出结果
//read()一般编写到某个循环中,返回0(表明关闭连接)或负值(表明发生错误)
while( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0;
if(fputs(recvline, stdout) == EOF) {
err_sys("fputs error");
}
}
if(n < 0) {
err_sys("read error");
}
return 0;
}