Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
C 线程不一致地打开发送套接字_C_Multithreading_Sockets_Gethostbyname - Fatal编程技术网

C 线程不一致地打开发送套接字

C 线程不一致地打开发送套接字,c,multithreading,sockets,gethostbyname,C,Multithreading,Sockets,Gethostbyname,我正在构建一个C程序,我正在努力解决gethostbyname的一个奇怪的、不一致的线程和套接字错误,这是我以前从未见过的 首先是一些环境方面的东西:我正在开发一个Ubuntu box,我的代码是用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程序,我正在努力解决gethostbyname的一个奇怪的、不一致的线程和套接字错误,这是我以前从未见过的

首先是一些环境方面的东西:我正在开发一个Ubuntu box,我的代码是用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来看看当我的服务器受到重击时会发生什么

让我带您浏览我的代码,然后描述问题。程序相对简单。有几个结构,然后是主结构。基本上,N=numThreads的主循环每次都创建一个分离的工作线程。每个线程都有一个填充的包结构,其中包含稍后将使用的信息:

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设置了什么值,有些工作线程成功地打开了套接字,有些则没有。失败的是调用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”(线程X启动)消息中肯定有一些错误,因为看起来线程0、1和6从未启动过,而线程3、7和9不知何故启动了两次。但是numThreads==10,并且10个线程已经启动,所以现在我将忽略这个问题

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

更奇怪的是,错误代码就是成功。如果它成功了。。。为什么通话失败了?我觉得我错过了一些非常非常明显的东西

这个问题前后矛盾,这也让我感到困扰。有时,当我测试这个时,7/10线程成功地发送。有时十分之一的人会这样做。我的平均成功率约为3/10。如果我对C有所了解的话,那就是不一致的问题通常表明变量已经成功创建,但尚未初始化。这里可能需要初始化什么?主机结构?我不确定

我已经在谷歌上搜索了大约三个小时,但是没有找到任何有用的东西。如有任何建议,我们将不胜感激

问题在于:

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

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

。。。您可以为新的线程包创建特定的资源,然后在线程完成其工作之前立即将其删除!这些免费呼叫应在流程结束时执行

查看此问题的答案:。这看起来确实是一个线程安全问题。还要检查手册页中的gethostbyname;它不会在错误上设置errno,而是设置h_errno。@MarkA嘿Mark-天哪,你的评论非常有用!我不知道gethostbyname存在全局内存问题。为了使用getaddrinfo,我不得不花几个小时重新安装代码,但这是值得的。感谢上帝你发现了这一点;如果您想使用多线程网络编程,这样的问题似乎很关键。为什么这些信息不在教程的前端和中心?伙计,如果你不插嘴,我会很痛苦的。接得好,非常感谢。我欠你一杯啤酒。@Pete gethostbyname已被弃用,你应该改用getaddrinfo。@RemyLebeau谢谢Remy。我为我的代码配备了getaddrinfo,现在它运行得越来越流畅。gethostbyname造成的破坏肯定比我想象的要大哇,谢谢Darren!你是100%正确的。我永远也不会明白这一点。我已经习惯于在调用malloc的同一个函数中将我的调用与free配对,所以我在这里没有考虑就这么做了。太棒了,谢谢你的帮助!
  pthread_create(&thread, NULL, process, (void*) pack);
  pthread_detach(thread);

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