使用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()。