我正在试图弄清楚什么阻碍了我的程序。我正在运行使用POSIX线程的服务器。我必须为我的计算机编程实验室。 main函数侦听新连接。一旦接受连接,它就会通过将FD传递给线程来创建新线程。我能够使用多个telnet /客户端连接成功连接到服务器。我可以成功地将数据发送到服务器一次,但如果我再次尝试发送,服务器将不会执行任何操作。
主要功能的一部分
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 <integer>\n2) Remove An Integer: remove <integer>\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)
{
perror("Unable to send");
}
memset(&buffer, 0, MESSAGELENGTH);
if (recv(bindfd, buffer, MESSAGELENGTH, 0) > 0)
{
//SOme other code
}
}
我认为它阻止接受或接受。我听说过select()和其他各种方法,但是我很难尝试实现它们。谢谢!
答案 0 :(得分:2)
您的问题的根本原因似乎是您无条件地在close(sockfd); return 0;
循环的底部执行while (running)
,这意味着循环只执行一次。
此外,除非您还使用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;
答案 1 :(得分:1)
默认情况下,网络套接字是阻塞的。您需要在套接字上设置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()。