我正在构建一个C程序,并且正在尝试使用gethostbyname()进行怪异且不一致的线程和套接字错误,这是我从未见过的。

首先考虑一些环境因素:我正在Ubuntu盒子上工作,并且我的代码是使用GCC编译的:

root@ubuntu:/home/me/socketProject# gcc -v
...
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
root@ubuntu:/home/me/socketProject#

目的是:我已经开发了另一个C程序,希望有一天它将成为网络服务。 服务器工作正常,但我需要对其进行压力测试。 因此,我构建了一个客户端程序,以模拟的网络请求对其进行轰炸。 服务器启动并侦听TCP 12345后,客户端程序只需执行以下操作:

  • N次,启动分离的工作线程
    • 每个线程应打开一个发送套接字,然后通过TCP 12345将一些数据发送到127.0.0.1
    • 发送后,线程应立即终止

这应该是孩子的游戏。 我想使用大量的N来查看服务器被重击时会发生什么。

让我逐步介绍我的代码,然后描述问题。 该程序相对简单。 有一些结构,然后是main() 基本上, main()循环N = numThreads ,每次都创建一个分离的工作线程。 每个线程都有一个填充的package结构,以及稍后将使用的信息:

typedef struct{
   int sock;
   struct sockaddr address;
   int addr_len;
} connection_t;

typedef struct{
   char* IP;
   int port, myNum;
} package;


void process(void* pack);                  // code for the thread, see below...


int main( int argc, char ** argv ){
   pthread_t  thread;
   int        numThreads = 10;             // or 100 or 1000 or whatever
   char       svrIP[20] = "127.0.0.1";
   int        portNumber = 12345;

   int i=0;
   for( ; i<numThreads; i++){

      package* pack   = (package*) malloc( sizeof(package) );
      pack->IP        = (char*) malloc( sizeof(char) * 20 );
      strcpy( pack->IP, svrIP );
      pack->port      = portNumber;
      pack->myNum     = i;

      pthread_create(&thread, NULL, process, (void*) pack);
      pthread_detach(thread);

      free( pack->IP );
      free( pack );
   }

   sleep(1);

   printf("END OF PROGRAM\n");
   return 0;
}

不管我为numThreads设置了什么,上面的一切都很numThreads 现在查看线程的代码。 出生时,线程尝试打开套接字,然后发送文本字符串。 然后线程终止。 请注意gethostbyname()周围的所有fprintf()代码–我将在以后参考它:

void process(void* pack){
   int                  len, sock = -1;
   struct sockaddr_in   address;
   struct hostent *     host;

   char* msg = "Some text string here for the server...";

   printf("THREAD %d STARTED:  %s  --  %d\n", ((package*)pack)->myNum, ((package*)pack)->IP, ((package*)pack)->port );

   // create the socket
   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (sock <= 0){
      fprintf( stderr, "Thread %d: error: cannot create socket\n", ((package*)pack)->myNum );
      pthread_exit(0);
   }

   // connect to server
   address.sin_family = AF_INET;
   address.sin_port = htons( ((package*)pack)->port );
   host = gethostbyname( ((package*)pack)->IP );
   if (!host){
      fprintf( stderr, "Thread %d: error: unknown host %s  --  Error is:  (%d) \”%s\”\n",
            ((package*)pack)->myNum,
            ((package*)pack)->IP,
            errno, strerror(errno));
      pthread_exit(0);
   }

   memcpy(&address.sin_addr, host->h_addr_list[0], host->h_length);
   if (connect(sock, (struct sockaddr *)&address, sizeof(address))){
      fprintf( stderr, "Thread %d: error: cannot connect to host %s\n", ((package*)pack)->myNum, ((package*)pack)->IP );
      pthread_exit(0);
   }

   printf("Thread %d: Sending message \”%s\”\n", ((package*)pack)->myNum, msg);

   len = strlen(msg);
   write(sock, &len, sizeof(int));
   write(sock, msg, len);

   printf("Thread %d: message sent, exiting...\n", ((package*)pack)->myNum );

   close(sock);

   pthread_exit(0);
}

好的,这就是代码。 所以这是问题:

无论我为numThreads设置什么值,一些工作线程都会成功打开套接字,而有些则不会。 失败的人在对gethostbyname()调用上失败。 查看以下内容; 我将numThreads设置为10,这意味着我应该看到线程0到9启动:

me@ubuntu:/home/me/socketProject# ./runTest
THREAD 2 STARTED:  127.0.0.1  --  24601
THREAD 5 STARTED:  127.0.0.1  --  24601
THREAD 3 STARTED:  127.0.0.1  --  24601
THREAD 3 STARTED:  127.0.0.1  --  24601
THREAD 4 STARTED:  127.0.0.1  --  24601
THREAD 7 STARTED:  127.0.0.1  --  24601
Thread 7: Sending message "Some text string here for the server..."
Thread 7: message sent, exiting...
THREAD 7 STARTED:  127.0.0.1  --  24601
Thread 7: Sending message "Some text string here for the server..."
Thread 7: message sent, exiting...
THREAD 8 STARTED:  127.0.0.1  --  24601
Thread 8: Sending message "Some text string here for the server..."
Thread 8: message sent, exiting...
THREAD 9 STARTED:    --  24601
THREAD 9 STARTED:    --  24601
Thread 9: Sending message "Some text string here for the server..."
Thread 9: message sent, exiting...
Thread 9: error: unknown host   --  Error is:  (0) "Success"
Thread 9: error: unknown host   --  Error is:  (0) "Success"
Thread 9: error: unknown host   --  Error is:  (0) "Success"
Thread 9: error: unknown host   --  Error is:  (0) "Success"
Thread 9: error: unknown host   --  Error is:  (0) "Success"
Thread 9: error: unknown host   --  Error is:  (0) "Success"
END OF PROGRAM
me@ubuntu:/home/me/socketProject#

如上面的输出所示,服务器收到了四个测试消息。

太好了…这里发生了很多怪异事件。 这些“ THREAD X STARTED ”消息一定存在一些错误,因为看起来线程0、1和6从未启动,而线程3、7和9两次启动了。 但是numThreads == 10并且启动了十个线程,因此我numThreads将忽略该问题。

更令人担忧的是,六个线程在调用gethostbyname()失败。 我承认:对于这段代码,我从教科书中复制了一个示例,但我不记得我从哪里得到它。 但是我想知道if if(!host)语句是否有意义。 当我在非线程版本中进行Beta版测试时没有问题,但是现在…

更奇怪的是,Errno代码是“成功”。 如果成功...为什么通话失败? 我觉得我确实缺少某些非常明显的东西。

这也困扰着我,这个问题是不一致的。 有时,当我对此进行测试时,成功发送了7/10个线程。 有时是1/10。 我的平均成功率约为3/10。 如果我对C有所了解,则其不一致的问题通常表示变量已成功创建但尚未初始化。 在这里可能需要初始化什么? host结构? 我不确定。

我已经在谷歌上搜索了大约三个小时,但没有拉出任何有用的东西。 任何建议或意见将不胜感激。

#1楼 票数:1 已采纳

问题在这里:

  pthread_create(&thread, NULL, process, (void*) pack);
  pthread_detach(thread);

  free( pack->IP );
  free( pack );

...您为新线程( pack )创建了特定的资源,然后在线程完成其工作之前立即将其删除! 这些以免费电话应在年底进行process

  ask by Pete translate from so

未解决问题?本站智能推荐:

1回复

gethostbyname()进程甚至从不同的线程一致地解决?

我通过gethostbyname()从不同的线程进行了DNS解析实验。 我关闭了网络链接并运行下面的程序。 输出是这样的 gethostbyname()同时启动,但是在40秒超时的情况下逐个完成。 然后我用getaddrinfo()进行了实验。 看起来这个功能不会遇到这个问题
2回复

UDP套接字广播和ifaddrstruct

我必须开发的应用程序的客户端存在问题。 我必须实现的第一阶段是对网络进行“扫描”,搜索其他用户。 我决定使用UDP套接字,它们可以正常工作。 如果我使用广播IP地址(getnamebyhost(“ 192.168.1.255”)),则可以正常工作。 问题是该应用程序必须在不同的网络上工
2回复

套接字主机名查找超时:如何实现?

我编写了使用套接字的可移植Windows / Linux应用程序。 我使用gethostbyname函数执行DNS查找。 但是,我看不到如何设置gethostbyname超时以及如何防止我的应用程序在名称查找期间挂起。 当然,可以在另一个线程上运行gethostbyname ,这就是我要做
1回复

c中的gethostbyname与gethostbyname(“www.google.com”)一起使用,但与我的char不一起使用*

在执行gethostbyname("www.google.com")时, gethostbyname可以工作,但是在执行以下操作时: 连接超时。 我确保在函数之前修剪掉我的字符串,以确保其中没有任何时髦的字符。 我不明白这个问题。
2回复

从子线程调用时,getaddrinfo和gethostbyname崩溃?

我们创建了一个在Ubuntu上运行的多线程单核应用程序。 当我们从主进程调用getaddrinfo和gethostbyname ,它不会崩溃。 但是,当我们从主进程创建线程并且从创建的线程调用函数getaddrinfo和gethostbyname ,它总是崩溃。 请帮助。 请在下面
1回复

如何使用C套接字接收和发送不同的线程

我试图在不同的线程中发送和接收。 当我使用下面的代码时,我得到一个错误的地址错误,我猜想是因为我的服务器地址无法正确传递给线程函数。 码: 我该如何解决该问题?
1回复

从URL获取IP(C++)

如何从具有顶级域名的域名中获取 IP 地址? 在本例中获取 google.com 的 IP。 如果可能的话,在 IPv6 中以正确的格式。 这是我迄今为止尝试过的:
3回复

使用C的套接字和线程

我是套接字和线程的新手。 我有这个代码: 如何为每个新连接启动新线程,而不是为每个请求启动? 当新连接进入时,应该启动这些线程,然后这些线程应该等待请求,处理这些请求,最后在关闭连接时返回。 每个连接应该有一个线程。 这是run_thread的代码: 谁能帮我? 谢谢。