www.pudn.com > pthread_examples.rar > dthread2.c
#include#include #include #include #include #include #include #include #include #include #include #include #define DICE_PORT 6173 int do_debug = 0; int do_thread = 0; int do_stdin = 0; int do_sleep = 0; pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; /*此处静态初始化线程锁*/ int threadcount = 0; struct sockets { int local; FILE *in, *out; }; struct sockets *get_sockets(int); int socket_setup(void); int debug(char *, ...); int fail(char *, ...); int warn(char *, ...); int roll_die(int); void *roll_dice(void *); void spawn(struct sockets *); int debug(char *fmt, ...) { va_list ap; int r; va_start(ap, fmt); if (do_debug) { r = vfprintf(stderr, fmt, ap); } else { r = 0; } va_end(ap); return r; } int warn(char *fmt, ...) { int r; va_list ap; va_start(ap, fmt); r = vfprintf(stderr, fmt, ap); va_end(ap); return r; } int fail(char *fmt, ...) { int r; va_list ap; va_start(ap, fmt); r = vfprintf(stderr, fmt, ap); exit(1); /* notreached */ va_end(ap); return r; } /*投骰子,获取一个随机数*/ int roll_die(int n) { return rand() % n + 1; } /* read dice on standard input, write results on standard output */ /*在标准输入上读入骰子,将结果在标准输出上输出*/ void * roll_dice(void *v) { printf("roll_dice running!\n"); struct sockets *s = v; char inbuf[512]; /* think globally, program defensively */ if (!s || !s->out || !s->in) return NULL; fprintf(s->out, "enter die rolls, or q to quit\n"); /*程序在此不断地读取数据*/ while (fgets(inbuf, sizeof(inbuf), s->in) != 0) { int dice; int size; /*对退出的处理*/ if (inbuf[0] == 'q') { /*表示该线程退出*/ fprintf(s->out, "buh-bye!\n"); if (s->local == 0) { shutdown(fileno(s->out), SHUT_RDWR); } fclose(s->out); fclose(s->in); if (s->local == 0) { free(s); } pthread_mutex_lock(&count_mutex); --threadcount; /* last one out closes the lights */ if (threadcount == 0) exit(0); /*如果所有的用户都退出该程序,则退出程序*/ pthread_mutex_unlock(&count_mutex); return 0; } if (sscanf(inbuf, "%dd%d", &dice, &size) != 2) { fprintf(s->out, "Sorry, but I couldn't understand that.\n"); } else { int i; int total = 0; for (i = 0; i < dice; ++i) { int x = roll_die(size); total += x; fprintf(s->out, "%d ", x); fflush(s->out); if (do_sleep) /*如果指定do_sleep,则没停顿一秒投一次骰子*/ sleep(1); } fprintf(s->out, "= %d\n", total); } } return 0; } int main(int argc, char *argv[]) { int o; int sock; /*getopt读取参数结束时返回-1*/ while ((o = getopt(argc, argv, "dstS")) != -1) { switch (o) { case 'S': do_sleep = 1; break; case 'd': do_debug = 1; break; case 's': /*指定了s, 进入控制台程序运行方式*/ do_stdin = 1; break; case 't': do_thread = 1; break; } } if (do_thread) { /*启动线程锁使线程运行*/ /* set up mutex for thread counting */ pthread_mutex_init(&count_mutex, NULL); } if (do_stdin) { struct sockets s; s.local = 1; s.in = stdin; /*指向标准输入*/ s.out = stdout; /*指向标准输出*/ if (do_thread) { spawn(&s); } else { roll_dice(&s); exit(0); } } sock = socket_setup(); while (1) { /*获取监听socket,如果没有连接进来,accept会被阻塞,除非设置成非阻塞*/ struct sockets *s = get_sockets(sock); if (s) { if (do_thread) { spawn(s); } else { roll_dice(s); exit(0); } } } return 0; } /*该函数用于建立socket*/ int socket_setup(void) { struct protoent *tcp_proto; struct sockaddr_in local; int r, s, one; tcp_proto = getprotobyname("tcp"); /*依据协议名称来获取协议的其他资料*/ if (!tcp_proto) { fail("Can't find TCP/IP protocol: %s\n", strerror(errno)); } /*tcp_proto->p_proto为tcp对应的通信协议的编号*/ s = socket(PF_INET, SOCK_STREAM, tcp_proto->p_proto); if (s == -1) { fail("socket: %s\n", strerror(errno)); } /*设置socket选项的参数*/ one = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); memset(&local, 0, sizeof(struct sockaddr_in)); local.sin_family = AF_INET; local.sin_port = htons(DICE_PORT); /*将socket与地址,端口绑定在一起*/ r = bind(s, (struct sockaddr *) &local, sizeof(struct sockaddr_in)); if (r == -1) { fail("bind: %s\n", strerror(errno)); } /*在绑定的socket上实现监听*/ r = listen(s, 5); if (r == -1) { fail("listen: %s\n", strerror(errno)); } return s; } struct sockets * get_sockets(int sock) { int conn; if ((conn = accept(sock, NULL, NULL)) < 0) { warn("accept: %s\n", strerror(errno)); return 0; } else { struct sockets *s; s = malloc(sizeof(struct sockets)); if (s == NULL) { warn("malloc failed.\n"); return 0; } s->local = 0; s->in = fdopen(conn, "r"); /*将s->in流关联到conn文件描述符上*/ s->out = fdopen(conn, "w"); setlinebuf(s->in); /*将相应的流关联为行缓存方式*/ setlinebuf(s->out); return s; } } /*spawn创建一个线程,并不断地执行线程回调函数*/ /*如果一个线程正在创建,另一个线程退出,会出现竞态*/ void spawn(struct sockets *s) { pthread_t p; pthread_mutex_lock(&count_mutex); pthread_create(&p, NULL, roll_dice, (void *) s); printf("spawn running\n"); ++threadcount; /*用于线程创建计数*/ pthread_mutex_unlock(&count_mutex); }