使用Unix和C / C ++帮助阻止套接字

我正在试图弄清楚什么阻碍了我的程序。 我正在运行使用POSIX线程的服务器。 我必须为我的计算机编程实验室。 main函数侦听新连接。 一旦接受连接,它就会通过将FD传递给线程来创建新线程。 我能够使用多个telnet /客户端连接成功连接到服务器。 我可以成功地将数据发送到服务器一次,但如果我再次尝试发送,服务器将不会执行任何操作。

部分主要function

int active_thread = 0; //The Running loop while(running) { if(active_thread > NUMBTHREADS) { printf("Unable to accept client connection! Threads are all used up"); running = false; } else { if(FD_ISSET(sockfd, &readfds)) { if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1) { fprintf(stderr, "Unable to accept client \n"); perror("What"); break; } activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]); //close(bindfd[active_thread]); //pthread_join( threads[active_thread], NULL); active_thread++; //running = false; } } } close(sockfd); return 0; } 

POSIX线程代码的一部分

 void *server_handler( void *sockfd) { int bindfd = *( (int *) sockfd); char buffer[MESSAGELENGTH]; bool running = true; printf("Thread was created successfully\n"); char intro[] = "Successfully Connected to server!\n"; struct pollfd pfd; pfd.fd = bindfd; pfd.events = POLLIN; if ( (send(bindfd, intro, strlen(intro), 0)) < 0) { perror("Unable to send"); } while(running){ char msg[] = "\nYou have the following options!\n1) Insert an integer: insert \n2) Remove An Integer: remove \n3) Get number of integers in list: get_count\n4) Get first integer: get_first\n5) Get last integer: get_last\n6) Quit program: quit\n "; if ( (send(bindfd, msg, strlen(msg), 0))  0) { //SOme other code } } 

我认为它阻止接受或接受。 我听说过select()和其他各种方法,但是我很难尝试实现它们。 谢谢!

问题的根本原因似乎是您无条件执行close(sockfd); return 0; close(sockfd); return 0;while (running)循环的底部,这意味着循环只执行一次。

此外,除非您还使用select()否则不应使用FD_ISSET() select() 。 你的主循环看起来应该更像:

 int active_thread = 0; while (active_thread < NUMBTHREADS) { if((bindfd[active_thread] = accept(sockfd, (struct sockaddr *) &client_addr, &client_sock_size)) == -1) { fprintf(stderr, "Unable to accept client \n"); perror("What"); break; } activethreads[active_thread] = pthread_create( &threads[active_thread], NULL, server_handler, (void*) &bindfd[active_thread]); active_thread++; } if (active_thread >= NUMBTHREADS) { printf("Unable to accept client connection! Threads are all used up.\n"); } running = false; close(sockfd); return 0; 

默认情况下,网络套接字是阻塞的。 您需要在套接字上设置O_NONBLOCK标志。

 if(fcntl(fd, F_GETFL, &flags) < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) perror("Failed to set socket as non-blocking"); 

现在,当没有输入(或缓冲空间来存储输出)时,不是阻塞,而是返回错误EAGAIN(或EWOUDLBLOCK)。 最后,除了等待I / O之外,您还需要使用select()或poll()。 当有输入,输出空间或可能超时时间过去时,这些调用只会唤醒进程。

 int maxFd; fdset fds; FD_ZERO(&fds); FD_SET(listenFd, &fds); FD_SET(sockFd1, &fds); FD_SET(sockFd2, &fds); maxFd = listenFd+1; maxFd = sockFd1 > maxFd ? sockFd1+1 : maxFd; maxFd = sockFd2 > maxFd ? sockFd2+1 : maxFd; if(select(maxFd, &fds, &fds, &fds, NULL) < 0) { perror("Failed on select()"); exit(1); } if(FD_ISSET(listenFd, &fds)) ... 

此示例不完整或必须100%正确,但应该是一个良好的开端。 此外,我倾向于在处理SOCK_DGRAM套接字时保留使用send *()和recv *(),并且只在SOCK_STREAM套接字上使用read(),write()。