$ pwd /home/jhl/working/myapp/server $ ls main.out Makefile server.c server.d server.o $ $ cat server.c // server.c // 1628872598@qq.com // ref: The Linux Programming inTerface, sec 56.5, tlpi-disk/sockets/is_seqnum_sv.c #include #include #include #include #include #include #include #include #define PORTNO "12345" #define BACKLOG 5 int main(void) { struct addrinfo hints, *result, *rp; struct sockaddr addr; socklen_t addrlen; int lfd, afd, optval; int rt; int errsv = 0; char host[NI_MAXHOST]; char service[NI_MAXSERV]; char buf[128] = {'\0'}; time_t tm; memset(&hints, 0, sizeof hints); hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; rt = getaddrinfo(NULL, PORTNO, &hints, &result); errsv = errno; if (rt){ printf("%s: %s\n", "getaddrinfo gai_strerror", gai_strerror(rt)); if (errsv) perror("getaddrinfo"); return rt; } optval = 1; for (rp = result; rp; rp = rp->ai_next){ lfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (lfd == -1) continue; if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1){ perror("setsockopt"); return -1; } if (!bind(lfd, rp->ai_addr, rp->ai_addrlen)) break; close(lfd); } if (!rp){ printf("Could not bind socket to any address\n"); return !rp; } if (listen(lfd, BACKLOG) == -1){ perror("listen"); return -1; } freeaddrinfo(result); for (;;){ addrlen = sizeof addr; afd = accept(lfd, &addr, &addrlen); if (afd == -1){ perror("accept"); continue; } if (!getnameinfo(&addr, addrlen, host, NI_MAXHOST, service, NI_MAXSERV, 0)) printf("Connection from %s %s\n", host, service); else printf("Unknown %s %s\n", host, service); for (;;){ // recv memset(buf, 0, sizeof buf); rt = recv(afd, buf, sizeof buf - 1, MSG_DONTWAIT); errsv = errno; if (rt == -1){ printf("%s: %s\n", "recv", strerror(errsv)); if (errsv == ECONNREFUSED || errsv == ENOTCONN || errsv == ECONNRESET){ close(afd); break; } } if (rt == 0){ printf("%s: %s\n", "recv", "Peer has performed an orderly shutdown"); close(afd); break; } if (strlen(buf)) printf("recv: client time: [%d] %s", strlen(buf), buf); else printf("[NODATA]\n"); fflush(stdout); // send time(&tm); snprintf(buf, sizeof buf, "%s", ctime(&tm)); rt = send(afd, buf, strlen(buf), MSG_DONTWAIT); errsv = errno; if (rt == -1){ printf("%s: %s\n", "send", strerror(errsv)); if (errsv == ECONNRESET || errsv == ENOTCONN || errsv == EPIPE){ close(afd); break; } } sleep(1); } } } $ $ pwd /home/jhl/working/myapp/client $ ls client.c client.d client.o main.out Makefile $ $ cat client.c // client.c // 1628872598@qq.com // ref: The Linux Programming inTerface sec 56.5, tlpi-dist/sockets/is_seqnum_cl.c #include #include #include #include #include #include #define PORTNO "12345" int main(int argc, char *argv[]) { struct addrinfo hints, *result, *rp; int fd; int rt; int errsv = 0; char buf[128] = {'\0'}; time_t tm; if (argc < 2){ printf("%s \n", argv[0]); return -1; } memset(&hints, 0, sizeof hints); hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; rt = getaddrinfo(argv[1], PORTNO, &hints, &result); errsv = errno; if (rt){ printf("%s: %s\n", "getaddrinfo gai_strerror", gai_strerror(rt)); if (errsv) perror("getaddrinfo"); return rt; } for (rp = result; rp; rp = rp->ai_next){ fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (fd == -1) continue; if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) break; close(fd); } if (!rp){ printf("Could not connect socket to any address\n"); return !rp; } freeaddrinfo(result); for (;;){ // send time(&tm); snprintf(buf, sizeof buf, "%s", ctime(&tm)); rt = send(fd, buf, strlen(buf), MSG_DONTWAIT); errsv = errno; if (rt == -1){ printf("%s: %s\n", "send", strerror(errsv)); if (errsv == ECONNRESET || errsv == ENOTCONN || errsv == EPIPE){ close(fd); break; } } // recv memset(buf, 0, sizeof buf); rt = recv(fd, buf, sizeof buf - 1, MSG_DONTWAIT); errsv = errno; if (rt == -1){ printf("%s: %s\n", "recv", strerror(errsv)); if (errsv == ECONNREFUSED || errsv == ENOTCONN || errsv == ECONNRESET){ close(fd); break; } } if (rt == 0){ printf("%s: %s\n", "recv", "Peer has performed an orderly shutdown"); close(fd); break; } if (strlen(buf)) printf("recv: server time: [%d] %s", strlen(buf), buf); else printf("[NODATA]\n"); fflush(stdout); sleep(1); } close(fd); return 0; } $ $ cat Makefile # Visual Stupid Makefile 1628872598@qq.com # Layout: [include/] src/ # All .c and Makefile in src, .h can be in include. No other sub-directories. # Project related: CPPFLAGS # .cpp, CXX, CXXFLAGS for C++ OUT = main.out SRCS = $(wildcard *.c) OBJS = $(patsubst %.c,%.o,$(SRCS)) CC = gcc CXX = g++ CFLAGS = -std=c99 -Wall -W CXXFLAGS = -std=c++0x -Wall -W CPPFLAGS = -I ../include LDFLAGS = CFLAGS += -g #CFLAGS += -DNDEBUG CFLAGS += -D_POSIX_SOURCE -D_BSD_SOURCE LDFLAGS += $(OUT): $(OBJS) $(CC) $(LDFLAGS) $^ -o $@ include $(SRCS:.c=.d) %.d: %.c @set -e; rm -f $@; \ $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ .PHONY : clean clean: rm *.d *.d.* $(OBJS) $(OUT) $ Screenshot: https://public.sn2.livefilestore.com/y1piEZTEe_epMlD_bItB4B4gOe6kZep4JDwJcGYSQL3GL0Q-CFgTQRIu_3-8ePa35JPCy5XzX2-M9iiFujXNP3RLA/server.png?psid=1 https://public.sn2.livefilestore.com/y1pF1dbaT4I33KHodiCwSUKq8G55C68Av2r7WsoXGEFOXeBmKnr1fHf1hyRvCQiQREDJIUbSrVhzA2gCnC52Xb5WA/client.png?psid=1