Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
选择不指示pthread_create启动的函数中的数据到达_C_Select_Pthreads - Fatal编程技术网

选择不指示pthread_create启动的函数中的数据到达

选择不指示pthread_create启动的函数中的数据到达,c,select,pthreads,C,Select,Pthreads,我编写了一个简单的多线程TCP echo服务器,用于试验线程。下面是我的主要功能的代码 #include "server_lib.h" #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <errno.h> int main(int argc, char *argv[]) { Server s = setup_socket(); pthread_t

我编写了一个简单的多线程TCP echo服务器,用于试验线程。下面是我的主要功能的代码

#include "server_lib.h"
#include <stdio.h>
#include <stdlib.h>

#include <pthread.h>
#include <errno.h>


int main(int argc, char *argv[]) {
  Server s = setup_socket();
  pthread_t clients[MAX_CLIENT];

  int connfd, rv = 0;

  client_data.client_number = 0;
  for(;;) {
    connfd = accept(s.sockfd, (struct sockaddr*)&s.sa, (socklen_t*)&s.addrlen);

    if (connfd < 0 && errno != EAGAIN)
      handle_error("accept failed");

    if (connfd > 0) {
      client_data.client_number++;
      if (client_data.client_number <= MAX_CLIENT) {
        socket_nonblocking(&connfd);
        disable_nagles_algo(&connfd);

        /* Send the client number to client first */
        rv = send(connfd, (void *)&client_data.client_number,
                  sizeof(client_data.client_number), 0);
        ThreadDataT *t = (ThreadDataT*)malloc(sizeof(ThreadDataT));
        t->fd = connfd;

        if (pthread_create(&clients[client_data.client_number-1], NULL, HandleMessage, (void*)t) != 0){
          handle_error("pthread_create failed");
        }
        /* Lets close our copy of connfd */
      }
        else {
          rv = send(connfd, "Max clients reached!\n", 21, 0);
          client_data.client_number--;
          close(connfd);
        }
    }

    usleep(100000);
  }

  close(s.sockfd);
}
下面是通过pthread_create调用的HandleMessage函数的代码

void* HandleMessage(void *data) {
  /* Lets detach first */
  pthread_detach(pthread_self());

  struct timeval timeout;
  timeout.tv_sec = 0;
  timeout.tv_usec = 0;

  ThreadDataT *t = (ThreadDataT*)data;
  fd_set testfd;

  FD_ZERO(&testfd); FD_SET(t->fd, &testfd);

  int rv = 0;

  for (;;) {
    int result = select(FD_SETSIZE, &testfd, NULL, NULL, &timeout);
    if (result < 0) {
      perror("select failed");
      pthread_exit(&result);
    }


    if (result > 0) {
      if(FD_ISSET(t->fd, &testfd)) {
        /* We have some data */
        rv = echo_content(&t->fd);
        if (rv < 0) {
          if (rv != -10)
            perror("echo_content failed");
          close(t->fd);
          free(t);
          pthread_exit(NULL);
        }
      }
    }

    usleep(1000);
  }

  return 0;
}
下面是注释中要求的echo_内容函数的代码

int echo_content(int *connfd) {
  unsigned char buffer[2048];
  int size = recv(*connfd, buffer, sizeof(buffer), 0);
  if (size < 0)
    handle_error("recv");

  if (size > 0) {
    if (strstr((const char*)buffer, "quit") != NULL){
      printf("Closing connection with client\n");
      send(*connfd, "bye\n", 4, 0);
      return -10;
    }

    size = send(*connfd, buffer, size, 0);
  } else
    printf("WARNING: Failed to recieve data\n");

  return size;
}
代码使用的数据结构定义如下

#ifndef __SERVER_LIB_H__
#define __SERVER_LIB_H__

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>

#define handle_error(msg) \
  do { perror(msg); exit(EXIT_FAILURE); } while(0)

#define PORT 50000
#define MAX_CLIENT 2

typedef struct {
  int sockfd;
  struct sockaddr_in sa;
  int addrlen;
} Server;

typedef unsigned char ClientNumber;

typedef struct {
  ClientNumber clients[MAX_CLIENT];
  short client_number;
} ClientDataT;

ClientDataT client_data;;

typedef struct {
  int fd;
} ThreadDataT;

Server setup_socket(void);
int echo_content(int *);
void socket_nonblocking(int *);
void disable_nagles_algo(int *);
void* HandleMessage(void*);

#endif /* __SERVER_LIB_H__ */
编译上述代码后,我可以使用telnet连接到它。我在telnet中没有看到服务器发送的客户端号码。接下来,我输入了一些信息,并期望它会回响,但这并没有发生

调试时,我注意到无论在客户端输入什么,SelectSystemCallinHandleMessage始终返回0。为了进行测试,我设置了select的writefds参数,然后select返回值>0,表示套接字需要写入。同样的代码用于fork模型。基于fork的代码是


这段代码几乎和基于fork的代码相似,所以我有点不明白它为什么不起作用。有人能告诉我我哪里做错了吗?

可能还有其他问题,但请尝试将FD_集移动到循环中:

  for (;;) {
    FD_SET(t->fd, &testfd);
    int result = select(FD_SETSIZE, &testfd, NULL, NULL, &timeout);
AFIK,选择call modify fd sets,可以从集合中删除testfd

另一个可能的问题是select调用的零超时。select的手册页显示:

如果 timeval结构为零,然后选择立即返回。这 用于轮询。如果timeout为NULL,则选择no timeout 可以无限期地阻止

您也可以尝试无限期超时:

  for (;;) {
    FD_SET(t->fd, &testfd);
    int result = select(FD_SETSIZE, &testfd, NULL, NULL, NULL);

这样就可以删除丑陋的轮询睡眠:usleep1000

“插座不阻塞&connfd;”为什么,当您在处理clientserver套接字时?'rv=echo\u content&t->fd;'每个客户端服务器一个线程中的所有select gunge是怎么回事?嗨,Martin,非阻塞代码来自原始的遗留代码库。是的,我可以放下它。此外,我还添加了echo_内容函数的定义。代码可以不使用select,我知道,但我只是好奇为什么select不表示数据的到达。谢谢你,FD_SET是键:-。同样是的,使用0超时然后睡眠确实没有意义。我已经更新了代码,使select无限期阻塞,并放弃了睡眠。