这个小案例主要是演示了服务端客户端通信,时间获取和设定的函数均是从网络上查询的,代码可以顺利编译运行,具体请查看代码和注释。
服务端代码
#include <string.h> #include <netinet/in.h> #include <stdio.h> #include <unistd.h> #include <strings.h> #include <arpa/inet.h> #include <ctype.h> #include <time.h> #include "wrap.h" #define MAXLINE 80 #define SRV_PORT 8000 void datetime(char* _datetime) { // 取当前时间到结构体中 time_t t = time(NULL); struct tm* stime = localtime(&t); // 格式化时间内容 strftime(_datetime, 20, "%F %H:%M:%S", stime); } int main(int argc, char* argv[]) { socklen_t cnt_len; struct sockaddr_in srv_addr, cnt_addr; int sock, conn; int n, i; pid_t pid; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; sock = Socket(AF_INET, SOCK_STREAM, 0); bzero(&srv_addr, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(SRV_PORT); Bind(sock, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); Listen(sock, 20); printf("Accepting connections ...\n"); while (1) { cnt_len = sizeof(cnt_addr); conn = Accept(sock, (struct sockaddr*)&cnt_addr, &cnt_len); printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cnt_addr.sin_addr, str, sizeof(str)), ntohs(cnt_addr.sin_port)); pid = fork(); if (pid == 0) { Close(sock); char time[20]; datetime(time); Write(conn, time, sizeof(time)); Close(conn); return 0; } else if (pid > 0) { Close(conn); } else { perr_exit("fork"); } } Close(sock); return 0; }
客户端代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <time.h> #include <linux/rtc.h> #define MAXLINE 80 #define SRV_PORT 8000 int SetSystemTime(char *dt) { struct rtc_time tm; struct tm _tm; struct timeval tv; time_t timep; sscanf(dt, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday,&tm.tm_hour, &tm.tm_min, &tm.tm_sec); _tm.tm_sec = tm.tm_sec; _tm.tm_min = tm.tm_min; _tm.tm_hour = tm.tm_hour; _tm.tm_mday = tm.tm_mday; _tm.tm_mon = tm.tm_mon - 1; _tm.tm_year = tm.tm_year - 1900; timep = mktime(&_tm); tv.tv_sec = timep; tv.tv_usec = 0; if(settimeofday (&tv, (struct timezone *) 0) < 0) { printf("set system datatime error : "); fflush(stdout); perror(""); return -1; } else { printf("set local datetime success : %s\n", dt); } return 0; } int main(int argc, char* argv[]) { struct sockaddr_in srv_addr; int sock, conn; sock = Socket(AF_INET, SOCK_STREAM, 0); bzero(&srv_addr, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &srv_addr.sin_addr); srv_addr.sin_port = htons(SRV_PORT); int len; char buf[MAXLINE]; conn = Connect(sock, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); len = Read(sock, buf, sizeof(buf)); if (len != 0) { //char time[20]; //strncpy(time, buf, sizeof(time)); SetSystemTime(buf); } close(sock); return 0; }
公共头文件
/* wrap.h */ #ifndef __WRAP_H__ #define __WRAP_H__ void perr_exit(const char* s); int Accept(int fd, struct sockaddr* sa, socklen_t* salenptr); void Bind(int fd, const struct sockaddr* sa, socklen_t salen); void Connect(int fd, const struct sockaddr* sa, socklen_t salen); void Listen(int fd, int backlog); int Socket(int family, int type, int protocol); ssize_t Read(int fd, void* ptr, size_t nbytes); ssize_t Write(int fd, const void* ptr, size_t nbytes); void Close(int fd); ssize_t Readn(int fd, void* vptr, size_t n); ssize_t Writen(int fd, const void* vptr, size_t n); static ssize_t my_read(int fd, char* ptr); ssize_t Readline(int fd, void* vptr, size_t maxlen); #endif
#include <stdlib.h> #include <errno.h> #include <sys/socket.h> #include <stdio.h> #include <unistd.h> #include "wrap.h" void perr_exit(const char* s) { perror(s); exit(1); } int Accept(int fd, struct sockaddr* sa, socklen_t* salenptr) { int n; again: if ( (n = accept(fd, sa, salenptr)) < 0 ) { if ((errno == ECONNABORTED) || (errno == EINTR)) { goto again; } else { perr_exit("accept error"); } } return n; } void Bind(int fd, const struct sockaddr* sa, socklen_t salen) { if ( bind(fd, sa, salen) < 0 ) { perr_exit("bind error"); } } void Connect(int fd, const struct sockaddr* sa, socklen_t salen) { if ( connect(fd, sa, salen) < 0 ) { perr_exit("connect error"); } } void Listen(int fd, int backlog) { if ( listen(fd, backlog) < 0 ) { perr_exit("listen error"); } } int Socket(int family, int type, int protocol) { int n = socket(family, type, protocol); if ( n < 0 ) { perr_exit("socket error"); } return n; } ssize_t Read(int fd, void* ptr, size_t nbytes) { ssize_t n; again: if ( (n = read(fd, ptr, nbytes)) == -1) { if (errno == EINTR) { goto again; } else { return -1; } } return n; } ssize_t Write(int fd, const void* ptr, size_t nbytes) { ssize_t n; again: if ( (n = write(fd, ptr, nbytes)) == -1) { if (errno == EINTR) { goto again; } else { return -1; } } return n; } void Close(int fd) { if (close(fd) == -1) { perr_exit("close error"); } } ssize_t Readn(int fd, void* vptr, size_t n) { size_t nleft; ssize_t nread; char* ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nread = read(fd, ptr, nleft)) < 0 ) { if (errno == EINTR) { nread = 0; } else { return -1; } } else if (nread == 0) { break; } nleft -= nread; ptr += nread; } } ssize_t Writen(int fd, const void* vptr, size_t n) { size_t nleft; ssize_t nwritten; const char* ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ( (nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) { nwritten = 0; } else { return -1; } } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd, char* ptr) { static int read_cnt; static char* read_ptr; static char read_buf[100]; if (read_cnt <= 0) { again: if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0 ) { if (errno == EINTR) { goto again; } return -1; } else if (read_cnt == 0) { return 0; } read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } ssize_t Readline(int fd, void* vptr, size_t maxlen) { ssize_t n, rc; char c, *ptr; ptr = vptr; for (n = 1; n < maxlen; n++) { if ( (rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') { break; } } else if (rc == 0) { *ptr = 0; return n - 1; } else { return -1; } *ptr = 0; return n; } }
编译测试代码
编译客户端:gcc time_client.c wrap.c -o time_client
编译服务端:gcc time_server.c wrap.c -o time_server
运行效果(客户端要设定时间需要使用管理员身份运行):