如何获取时间
UNIX时间戳:从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。
UTC时间:世界协调时。以地球自转为基础的时间标准。 UTC表示方式为 年月日时分秒。
获取UNIX时间戳
C运行库:#include <sys/time.h>
运行环境: C语言运行环境
函数: gettimeofday(struct timeval* tv, struct timezone* tz)
功能: 获取当前UNIX时间戳
相关结构体:1
2
3
4
5
6
7
8
9struct timeval{
	long tv_sec;	//seconds
	long tv_usec;	//microSeconds
}
struct timezone{
	int tz_minuteswest;	//diff of greenwich
	int tz_dsttime;	//type of DST correction
}
获取UTC时间
C运行库:#include <time.h>
运行环境: C语言运行环境
函数1: char *ctime(const time_t *timer)
功能1: 将UNIX时间戳转化成   Www Mmm dd hh:mm:ss yyyy (Mon Aug 13 08:23:14 2012)形式
函数2: struct tm *gmtime(time_t *timer)
功能2: 将UNIX时间转化成struct tm结构。
相关结构体:1
2
3
4
5
6
7
8
9
10
11struct tm{
	int tm_sec;
	int tm_min;
	int tm_hour;
	int tm_mday;
	int tm_mon;
	int tm_year;
	int tm_wday;
	int tm_yday;
	int tm_isdst;
}
注意: UTC时间年是以1900为参考点,记时间时需要year+1900, 时区是0时区,如果按照北京时间(东8区)需要tm_hour+8
测试代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
struct tm *GetBeijingTime();
int main(){
	struct tm *beijingTime;
	beijingTime = GetBeijingTime();
	printf("%d/%d/%d %2.2d:%2.2d:%2.2d\n", beijingTime->tm_year,
		beijingTime->tm_mon, beijingTime->tm_mday, beijingTime->tm_hour,
		beijingTime->tm_min, beijingTime->tm_sec);
}
struct tm *GetBeijingTime(){
	struct timeval tv;
	struct tm *BeijingTime;
	gettimeofday(&tv, NULL);
	BeijingTime = gmtime((time_t*)&(tv.tv_sec));
	BeijingTime->tm_year += 1900;
	BeijingTime->tm_hour += 8;
	BeijingTime->tm_mon += 1;
	return BeijingTime;
}
Socket编程
包含的库:1
2#include <sys/socket.h>
#include <netinet/in.h>
服务器端
- 创建socket int socket(int domain, int type, int protocol)- domain: 协议域,决定了socket的地址类型。- AF_INET: 用于IPV4网络通信
- AF_UNIX: 单一Unix系统中进程间通信
- AF_INET6: 用于IPV6网络通信
 
- type: 制定socket类型。- SOCK_STREAM: 流式,一般用于TCP通信
- SOCK_DGRAM: 数据包式,一般用于UDP通信
 
- protocaol: 制定协议。 IPPROTO_TCP表示TCP协议,IPPROTO_UDP表示UDP协议,为0时自动选择type默认协议
- return: -1 错误; 非负值 成功
 
- domain: 协议域,决定了socket的地址类型。
- 绑定socket和端口号 - int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)- sockfd: socket返回的套间字描述符,类似于文件描述符。
- addr: 有个sockaddr类型数据的指针,指向的时被绑定结构变量 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- //IPV4的sockaddr地址结构 
 struct sockaddr_in{
 sa_family sin_family; //协议类型,AF_INET
 in_port_t sin_port; //端口号
 struct in_addr sin_addr; //ip地址
 };
 struct in_addr{
 uint32_t s_addr;
 }
 //有关于sockaddr的相关函数
 htons() 将整形类型转换成网络字节序 比如 htons(INADDR_ANY),让系统自动获取本地IP地址
 htonl() 将长整形转换为网络字节序
 inet_pton(int af, char *str, pvoid addrbuf) 将点分十进制IP地址转换成网络字节
 af: 协议域,与socket的domain一致
 str: 要转换的地址 127.0.0.1
 addrbuf: sinaddr的指针
 inet_ntop(int af, pvoid addrbuf, char *str, size_t len) 将网络字节序转换成分十进制IO地址
 af: 协议域,与socket的domain一致
 addrbuf: sinaddr的指针
 str: 转换成的地址
 len: 字节单位长度
- addrlen: 地址长度 
 
- 监听端口号 int listen(int sockfd, int backlog)- sockfd: 要监听的sock描述字
- backlog: socket可以排队的最大连接数
 
- 接收用户请求 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)- sockfd: 服务器socket描述字
- addr: 地址指针,保存用户对应的地址
- addrlen: 地址长度。保存用户地址的长度
- return: 一旦accept某个客户机请求成功,返回一个新的描述符,用于标识具体客户的TCP连接。
 
- 从socket中读取字符 ssize_t read(int fd, void *buf, size_t count)- fd: 读取的用户对应的套间字描述字
- buf: 保存接收信息的缓冲区
- count: 读取的长度
- return: 如果大于零表示读取的长度,返回0表示文件读取结束,小于0表示发生错误
 
- 向socket发送信息 ssize_t write(int fd, const void *buf, size_t count)- fd: 发送的用户对应的套间字
- buf: 缓冲区
- count: 发送的信息长度
- return: 如果大于零表示发送的长度,小于0表示发生错误
 
- 关闭socket int close(int fd)
- 创建socket int socket(int domain, int type, int protocol)- domain: 协议域,决定了socket的地址类型。- AF_INET: 用于IPV4网络通信
- AF_UNIX: 单一Unix系统中进程间通信
- AF_INET6: 用于IPV6网络通信
 
- type: 制定socket类型。- SOCK_STREAM: 流式,一般用于TCP通信
- SOCK_DGRAM: 数据包式,一般用于UDP通信
 
- protocaol: 制定协议。 IPPROTO_TCP表示TCP协议,IPPROTO_UDP表示UDP协议,为0时自动选择type默认协议
- return: -1 错误; 非负值 成功
 
- domain: 协议域,决定了socket的地址类型。
- 连接指定服务器 int connect(int sockfd, struct sockaddr *addr, socklen_t addrlen)- sockfd:客户端的sock描述字
- addr: 服务器的地址
- addrlen: socket地址长度
 
- 向socket发送信息 ssize_t write(int fd, const void *buf, size_t count)- fd: 发送的用户对应的套间字
- buf: 缓冲区
- count: 发送的信息长度
- return: 如果大于零表示发送的长度,小于0表示发生错误
 
- 关闭socket int close(int fd)- fd: accept返回的连接描述字,每个连接有一个,生命周期为连接周期。
 
实例
客户端连接服务器,服务器向客户端发送当地时间,客户端接收并显示。
服务器端:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define DEFAULT_PORT 6666
#define BUF_LEN 128
struct tm *GetBeijingTime();
int main(){
	int SocketServer;
	struct sockaddr_in ServerAddr;
	char Buf[BUF_LEN];
	
	//create socket
	if((SocketServer = socket(AF_INET, SOCK_STREAM, 0)) == -1){
		printf("create socket error!\n");
		exit(0);
	}
	
	//create addr
	memset((char*)&ServerAddr, 0, sizeof(ServerAddr));
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	ServerAddr.sin_port = htons(DEFAULT_PORT);
	
	//bind the socket with address
	if(bind(SocketServer, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)) == -1){
		printf("bind socket with addr fail!\n");
		exit(0);
	}
	
	//listen
	if(listen(SocketServer, 20) == -1){
		printf("listen error!\n");
		exit(0);
	}
	printf("server: waitting for client connect.........\n");
	
	//loop for accept
	while(1){
		int SocketClient;
		struct sockaddr_in ClientAddr;
		char ClientAddrString[30];
		socklen_t ClientAddrLen;
		if((SocketClient = accept(SocketServer, (struct sockaddr*)&ClientAddr, &ClientAddrLen)) == -1){
			printf("accept socket error!\n");
			exit(0);
		}
		inet_ntop(AF_INET, &ClientAddr.sin_addr, ClientAddrString, sizeof(ClientAddrString));
		printf("server: %s connecting .....\n", ClientAddrString);
		//get the time
		struct tm *beijingTime;
		beijingTime = GetBeijingTime();
		sprintf(Buf, "TIME: %d/%d/%d %2.2d:%2.2d:%2.2d\n", beijingTime->tm_year,
		beijingTime->tm_mon, beijingTime->tm_mday, beijingTime->tm_hour,
		beijingTime->tm_min, beijingTime->tm_sec);
		
		//send the time 
		if(write(SocketClient, Buf, strlen(Buf)) == 0)
			printf("server: send message error!\n");
		
		//close the socket connect
		close(SocketClient);
		printf("server: close the client\n");
	}
	close(SocketServer);
	
	return 1;
}
struct tm *GetBeijingTime(){
	struct timeval tv;
	struct tm *BeijingTime;
	gettimeofday(&tv, NULL);
	BeijingTime = gmtime((time_t*)&(tv.tv_sec));
	BeijingTime->tm_year += 1900;
	BeijingTime->tm_hour += 8;
	BeijingTime->tm_mon += 1;
	return BeijingTime;
}
客户端:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUF_LEN 128
int main(int argc, char** argv){
	int SocketClient;
	char Buf[BUF_LEN];
	struct sockaddr_in ServerAddr;
	
	//create socket
	if((SocketClient = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		printf("create socket error\n");
		exit(0);
	}
	//set the server's addr
	memset((char*)&ServerAddr, 0, sizeof(ServerAddr));
	ServerAddr.sin_family = AF_INET;
	int port = atoi(argv[2]);
	ServerAddr.sin_port = htons(port);
	if(inet_pton(AF_INET, argv[1], &ServerAddr.sin_addr) <= 0){
		printf("inet_pton error!\n");
		exit(0);
	}
	
	//connect
	if(connect(SocketClient, (struct sockaddr*)&ServerAddr, sizeof(struct sockaddr)) < 0){
		printf("connect error!\n");
		exit(0);
	}
	
	memset(Buf, 0, BUF_LEN);
	//read the message from server
	if(recv(SocketClient, Buf, BUF_LEN, 0) < 0){
		printf("recv error!!\n");
		exit(0);
	}
	printf("Client: recv from server-> %s\n", Buf);
	
	//close socket
	close(SocketClient);
	return 1;
}