服务端:
#include <pthread.h> #include <stdlib.h> #include <sys/socket.h> #include <netdb.h> #include <errno.h> #include <dirent.h> #include <string.h> #include <unistd.h> #include <stdio.h> #include <limits.h> #include <sys/types.h> #define DIRNAME "/proc" #define QUENUM 8 #define MAXSIZE 16 struct s_pronum { int pronum; char pronumbuf[MAXSIZE]; }; static pthread_key_t get_pronum_key; static pthread_once_t once = PTHREAD_ONCE_INIT; static void free_alloc_space(void *ptr) { free(ptr); } static void get_pronum_key_once(void) { pthread_key_create(&get_pronum_key, free_alloc_space); } static char * get_pronum(void) //get process number { int temp, count = 0; DIR *dp; struct dirent *dirp; struct s_pronum *ptr; pthread_once(&once, get_pronum_key_once); if ((ptr = pthread_getspecific(get_pronum_key)) == NULL) { if ((ptr = (struct s_pronum *)calloc(1, sizeof(struct s_pronum))) == NULL) { //calloc is not signal safe fprintf(stderr, "no available memery\n"); return(NULL); } pthread_setspecific(get_pronum_key, ptr); } ptr->pronum = 0; if ((dp = opendir(DIRNAME)) == NULL) { //open "/proc" to get process number fprintf(stderr, "opendir failure: %s\n", strerror(errno)); //errno is not reenterable, it's static variable return(NULL); } while((dirp = readdir(dp)) != NULL) { //get next struct dirent if (sscanf(dirp->d_name, "%d", &temp) > 0) //if the file name is numeric ,there is a process ptr->pronum++; } printf("process number is %d now\n", ptr->pronum); snprintf(ptr->pronumbuf, MAXSIZE, "%d", ptr->pronum); return(ptr->pronumbuf); } static void * send_pronum(void *data) { int err; int connfd; char *pronumbuf; connfd = *(int *)data; free(data); //free connfd memery for (; ;) { if ((pronumbuf = get_pronum()) == NULL) { fprintf(stderr, "get_pronum error\n"); pthread_exit(NULL); } if (write(connfd , pronumbuf, strlen(pronumbuf) + 1) < 0) { //sizeof(pronumbuf) is wrong fprintf(stderr, "write error: %s\n", strerror(errno)); pthread_exit(NULL); } printf("write done\n"); sleep(2); } } int main(int argc, char *argv[]) { int listenfd, *connfdp; int err; socklen_t len; struct addrinfo hint, *res, *restemp; struct sockaddr_in cliaddr; pthread_t tid; char clihost[MAXSIZE], cliport[MAXSIZE]; pthread_attr_t attr; if (argc != 2) { fprintf(stderr, "incorrect enter\n"); exit(1); } if ((err = pthread_attr_init(&attr)) != 0) { fprintf(stderr, "pthread_attr_init error: %s\n", strerror(err)); exit(1); } if ((err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) != 0) {//create detach pthread, also can use pthread_detach fprintf(stderr, "pthread_attr_setdetachstat error: %s\n", strerror(err)); exit(1); } bzero(&hint, sizeof(hint)); hint.ai_flags = AI_PASSIVE; hint.ai_family = AF_INET; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0; if ((err = getaddrinfo(NULL, argv[1], &hint, &res) != 0)) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(err)); exit(1); } for (restemp = res; res != NULL; res = res->ai_next) { //get listen socket if ((listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) continue; if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) break; close(listenfd); } if (res == NULL) { fprintf(stderr, "no available address\n"); exit(1); } freeaddrinfo(restemp); if (listen(listenfd, QUENUM) != 0) { fprintf(stderr, "listen error: %s\n", strerror(errno)); exit(1); } printf("start accept request!\n"); for (; ;) { len = sizeof(cliaddr); if ((connfdp = malloc(sizeof(int))) == NULL) { //just in case, make connfd to be private fprintf(stderr, "no available memery\n"); exit(1); } if ((*connfdp = accept(listenfd, (struct sockaddr *)&cliaddr, &len)) < 0) { fprintf(stderr, "accept error: %s", strerror(errno)); continue; } if ((err = getnameinfo((struct sockaddr *)&cliaddr, sizeof(cliaddr), //get client host and port clihost, MAXSIZE, cliport,MAXSIZE, NI_NUMERICSERV)) != 0) { fprintf(stderr, "getnameinfo error: %s\n", gai_strerror(err)); return(1); } if (pthread_create(&tid, &attr, send_pronum, connfdp) != 0) { //once get a connfd , create a pthread immediately fprintf(stderr, "pthread_create error\n"); close(*connfdp); //if failure, close connection and free the memery we requested free(connfdp); } printf("pthread %ld connect to client %s port %s\n", tid, clihost, cliport); } exit(0); }
#include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #define MAXSIZE 20 int main(int argc, char *argv[]) { struct addrinfo hints, *res, *restemp; int err, sockfd; char buf[MAXSIZE]; if (argc != 3) { fprintf(stderr, "incorrect enter\n"); exit(1); } bzero(&hints, sizeof(hints)); hints.ai_flags = 0; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((err = getaddrinfo(argv[1], argv[2], &hints, &res)) != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(err)); exit(1); } for (restemp = res; restemp != NULL; restemp = restemp->ai_next) { if ((sockfd = socket(restemp->ai_family, restemp->ai_socktype, restemp->ai_protocol)) < 0) { fprintf(stderr, "socket error: %s\n", strerror(errno)); continue; } if (connect(sockfd, restemp->ai_addr, restemp->ai_addrlen) == 0) { printf("connect success\n"); break; } close(sockfd); } if (restemp == NULL) { fprintf(stderr, "no available address\n"); exit(1); } freeaddrinfo(res); while (read(sockfd, buf, MAXSIZE) != -1) { printf("process number on server is: %s\n", buf); sleep(2); } exit(0); }