所以我正在编写一个使用pthreads来管理所有IO的点对点聊天客户端,当我编译文件时,gcc给了我错误
client.c: In function ‘accepted_daemon’: client.c:115:1: error: expected ‘while’ before ‘void’ void * ^ client.c: In function ‘listen_daemon’: client.c:176:1: error: expected ‘while’ before ‘int’ int main(int argc, char *argv[]) ^
我的程序的源代码是
#include#include #include #include #include #include #include #include #include #define error(s, e, ...) error_at_line (s, e, __FILE__, __LINE__, __VA_ARGS__) #include #include #include #include #define PORT 3248 #define PROMPT "message: " struct accepted { int fd; struct sockaddr_in addr; }; struct value { struct accepted *acc; struct value *nxt; }; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; struct value *remote = NULL; void push_remote (struct accepted *acc) { pthread_mutex_lock (&mutex); struct value *s = malloc (sizeof *s); s->acc = acc; s->nxt = remote; remote = s; pthread_mutex_unlock (&mutex); } void pop_remote (struct accepted *acc) { pthread_mutex_lock (&mutex); struct value head = { NULL, remote }; struct value *s = &head; while (s->nxt->acc != acc) { s = s->nxt; if (s->nxt == NULL) return; } struct value *tmp = s->nxt->nxt; free (s->nxt); s->nxt = tmp; } struct accepted * make_socket (uint32_t s_addr) { struct accepted *addr = malloc (sizeof *addr); addr->fd = socket (PF_INET, SOCK_STREAM, 0); if (addr->fd < 0) { free (addr); return NULL; } addr->addr.sin_family = AF_INET; addr->addr.sin_port = htons (PORT); addr->addr.sin_addr.s_addr = s_addr; if (connect (addr->fd, (struct sockaddr *) &addr->addr, sizeof addr->addr) < 0) { free (addr); return NULL; } return addr; } void * accepted_daemon (void *arg) { pthread_cleanup_push (free, arg); struct accepted *args = arg; pthread_cleanup_push (close, args->fd); push_remote (args); pthread_cleanup_push (pop_remote, args); while (1) { char buffer[100]; ssize_t chars = read (args->fd, buffer, sizeof buffer); if (chars < 0) { error (0, errno, "Host %s disconnected", inet_ntop (AF_INET, arg, buffer, sizeof buffer)); return NULL; } write (1, buffer, chars); write (1, "\n", strlen ("\n") * sizeof (char)); } return NULL; } void * initial_connection (void *arg) { uint32_t host = (uint32_t) arg; struct accepted *acc = make_socket (arg); if (acc == NULL) { char buffer[100]; error (1, errno, "Failed to connect to host %s", inet_ntop (AF_INET, arg, buffer, sizeof buffer)); } while (1) { uint32_t nxthost; read (sock, &nxthost, sizeof nxthost); if (nxthost == 0) break; pthread_t thread; pthread_create (&thread, NULL, initial_connection, (void *) nxthost); } return accepted_daemon (acc); } void * listen_daemon (void *arg) { int sock = socket (PF_INET, SOCK_STREAM, 0); pthread_cleanup_push (close, sock); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (PORT); addr.sin_addr.s_addr = INADDR_ANY; bind (sock, (struct sockaddr *) &addr, sizeof addr); listen (sock, 5); while (1) { struct accepted *acc = malloc (sizeof *acc); socklen_t len; acc->fd = accept (sock, (struct sockaddr *) &acc->addr, &len); pthread_mutex_lock (&mutex); struct value *p = remote; while (p != NULL) { write (acc->fd, &p->acc->addr.sin_addr.s_addr, sizeof (uint32_t)); p = p->nxt; } pthread_mutex_unlock (&mutex); pthread_t thread; pthread_create (&thread, NULL, accepted_daemon, (void *) acc); } return NULL; } int main(int argc, char *argv[]) { assert (argc == 2); struct hostent *target = gethostbyname2 (argv[1], AF_INET); if (target == NULL) error (1, errno, "Host could not be found"); pthread_t thread; pthread_create (&thread, NULL, initial_connection, (void *) inet_addr (target->h_addr)); pthread_create (&thread, NULL, listen_daemon, NULL); char *in = readline (PROMPT); while (in != NULL) { pthread_mutex_lock (&mutex); struct value *p = remote; while (p != NULL) { write (p->addr->fd, in, strlen (in)); p = p->nxt; } pthread_mutex_unlock (&mutex); free (in); in = readline (PROMPT); } return 0; }
alk.. 15
pthread_cleanup_push()
最有可能实现为引入开放式大括号的宏,该大括号{
期望pthread_cleanup_pop()
在相同的上下文中(对应).后者然后服务闭合支架}
.*1
看一下代码的预处理器输出(当然还有相应的man-pages和header文件),你会得到启发.
*1这种实施方式,BTW,是我用来训练C编码员的最严格的方式......; - >
pthread_cleanup_push()
最有可能实现为引入开放式大括号的宏,该大括号{
期望pthread_cleanup_pop()
在相同的上下文中(对应).后者然后服务闭合支架}
.*1
看一下代码的预处理器输出(当然还有相应的man-pages和header文件),你会得到启发.
*1这种实施方式,BTW,是我用来训练C编码员的最严格的方式......; - >