C :: 线程不一致地打开发送套接字
C :: Threads Inconsistently Open a Sending Socket
我正在构建一个 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#
objective 这里:我开发了另一个 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
设置什么,上面的一切都很好用。现在是线程的代码。出生时,线程会尝试打开一个套接字,然后发送一个文本字符串。然后线程终止。请注意所有 fprintf()
围绕 gethostbyname()
的代码——我稍后会提到它:
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#
如以上输出所示,服务器收到了四条测试消息。
Sooooooooo…这里发生了很多奇怪的事情。那些“THREAD X STARTED”消息肯定有一些错误,因为看起来线程 0、1 和 6 从未启动过,而线程 3、7 和 9 不知何故启动了两次。但是 numThreads
== 10 并且启动了 10 个线程,所以我暂时忽略这个问题。
更令人担忧的是,六个线程在调用 gethostbyname()
时失败了。我承认:对于这段代码,我从教科书中复制了一个示例,但我不记得是从哪里得到的。但我想知道 if(!host)
声明是否有意义。我在非线程版本中测试时没有问题,但现在…
更奇怪的是 Errno 代码是 "Success." 如果成功...为什么调用失败?我觉得我错过了一些非常非常明显的东西。
同样困扰我的是这个问题不一致。有时当我测试这个时,7/10 线程成功发送。有时是 1/10。我的平均成功率约为 3/10。如果我对 C 有所了解,那么不一致的问题通常表明一个变量已成功创建但未初始化。这里可能需要初始化什么? host
结构?我不确定。
我已经用谷歌搜索了大约三个小时,但没有找到任何有用的东西。任何建议或意见将不胜感激。
问题在这里:
pthread_create(&thread, NULL, process, (void*) pack);
pthread_detach(thread);
free( pack->IP );
free( pack );
...您为新线程 (pack
) 创建了一个特定的资源,然后在该线程完成其工作之前立即将其删除!这些对 free 的调用应该在 process
结束时执行
我正在构建一个 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#
objective 这里:我开发了另一个 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
设置什么,上面的一切都很好用。现在是线程的代码。出生时,线程会尝试打开一个套接字,然后发送一个文本字符串。然后线程终止。请注意所有 fprintf()
围绕 gethostbyname()
的代码——我稍后会提到它:
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#
如以上输出所示,服务器收到了四条测试消息。
Sooooooooo…这里发生了很多奇怪的事情。那些“THREAD X STARTED”消息肯定有一些错误,因为看起来线程 0、1 和 6 从未启动过,而线程 3、7 和 9 不知何故启动了两次。但是 numThreads
== 10 并且启动了 10 个线程,所以我暂时忽略这个问题。
更令人担忧的是,六个线程在调用 gethostbyname()
时失败了。我承认:对于这段代码,我从教科书中复制了一个示例,但我不记得是从哪里得到的。但我想知道 if(!host)
声明是否有意义。我在非线程版本中测试时没有问题,但现在…
更奇怪的是 Errno 代码是 "Success." 如果成功...为什么调用失败?我觉得我错过了一些非常非常明显的东西。
同样困扰我的是这个问题不一致。有时当我测试这个时,7/10 线程成功发送。有时是 1/10。我的平均成功率约为 3/10。如果我对 C 有所了解,那么不一致的问题通常表明一个变量已成功创建但未初始化。这里可能需要初始化什么? host
结构?我不确定。
我已经用谷歌搜索了大约三个小时,但没有找到任何有用的东西。任何建议或意见将不胜感激。
问题在这里:
pthread_create(&thread, NULL, process, (void*) pack);
pthread_detach(thread);
free( pack->IP );
free( pack );
...您为新线程 (pack
) 创建了一个特定的资源,然后在该线程完成其工作之前立即将其删除!这些对 free 的调用应该在 process