C Programming :: accept() 在压力测试中工作然后不工作
C Programming :: accept() works and then doesn't, in stress-testing
我正在编写我认为是简单的 C 套接字程序的代码。该代码将充当原始服务器。它需要创建一个监听套接字,然后每次联系时,它需要accept()传入的连接,然后衍生出一个线程来处理一些基本的处理。我或多或少的线程和处理部分在工作,但是 accept() 部分在代码成功处理一些初始连接后出现故障。这是一个问题,因为我预计该程序将需要 运行 持续运行,并且可能必须处理大量传入请求。
首先是一些环境方面的东西:我正在开发一个 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#
我的 main() 函数设置一个监听套接字,然后开始一个无限循环。对于进入的每个连接,它都会尝试 accept() 然后将工作传递给分离的线程:
int main(int argc, char ** argv)
{
int sock = -1;
struct sockaddr_in address;
int port = 12345;
connection_t* connection;
pthread_t thread;
// Create the listening socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock <= 0){
fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
return -3;
}
// Bind socket to port
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0){
fprintf(stderr, "%s: error: cannot bind socket to port %d\n", argv[0], port);
return -4;
}
// Listen on the port
if (listen(sock, 5) < 0){
fprintf(stderr, "%s: error: cannot listen on port\n", argv[0]);
return -5;
}
// Listen forever...
while (1){
// Accept incoming connections
connection = (connection_t *)malloc(sizeof(connection_t));
printf("1) [[ sock: %d -- address: %s -- addr_len: %d ]]\n", connection->sock, &connection->address.sa_data, connection->addr_len );
connection->sock = accept(sock, &connection->address, &connection->addr_len);
printf("2) [[ sock: %d -- address: %s -- addr_len: %d ]]\n", connection->sock, &connection->address.sa_data, connection->addr_len );
if (connection->sock <= 0){
printf(" *** PROBLEM!!! Value of errno: %d\n ", errno);
free(connection);
}
else{
// Start a new thread but do not wait for it
pthread_create(&thread, 0, process, (void *)connection); // process() omitted
pthread_detach(thread);
}
}
return 0;
}
漂亮的教科书内容。当只有一个传入连接时,我制定了所有逻辑并使一切正常工作。
但后来我开始进行压力测试,并立即意识到我遇到了问题。我编写了一个客户端程序,它连续发送 X 个测试请求。上面的服务器代码对于一些初始请求工作正常,但随后就崩溃了。这是输出:
root@ubuntu:/home/me/socketProject# ./server
*** 1) [[ sock: 18954128 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 7 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18970816 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 8 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18962080 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 9 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18962112 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 10 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18954064 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 11 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18954160 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 12 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18907120 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 13 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18950880 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 14 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18961856 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 15 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18957136 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 17 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18957168 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
你看到问题了。在上面的例子中,大约十次成功请求后发生了一些事情,然后 accept() 开始抱怨 ERRNO 22。快速 Google 搜索显示 ERRNO 22 是“EINVAL:无效参数”,这显然不好。
我从学生时代开始就做过一些简单的套接字编程,但我以前从未遇到过 accept() 的问题。我真的很纳闷。在我看来,N-1 个请求到达并被 accept() 成功处理。但随后第 N 次出现,accept() 不喜欢它,套接字被破坏。怎么样,为什么,我不知道。
accept() 正在抱怨 "invalid argument(s)"。但是客户端实际上是一遍又一遍地发送完全相同的测试消息。 N-1 连接如何提供有效参数,但第 N、N+1、N+2... 参数无效?这让我大吃一惊。
一些观察:
这是非黑即白的现象。我的意思是
套接字在 100% 的时间里都能正常工作,但随后出现了一些问题
accept() 发生,然后套接字再也无法工作。
我测试了运行很多次,不知道有多少成功
当我开始一个新的测试时,我会得到连接。我有多达 88 个
在套接字停止工作之前成功连接。在另一个
测试,在套接字打开之前我只有 2 个成功的连接
肚皮。之前的平均成功连接数
插座断裂大约为 17.
我的客户端测试程序没有尝试 space 发出请求
发送;它只是打开一个套接字并开始轰炸我的服务器
以最快的速度编程。我这样做是因为我想进行压力测试。
但也许我的客户端程序发送测试请求的速度太快了
服务器跟上……?
我想也有可能是客户端程序导致
问题。我不这么认为,因为它只是发送相同的测试
消息一遍又一遍,它永远不会抛出错误。
有没有人见过这样的问题?我一直在寻找 SO 大约一个小时,但我找不到另一个 post 其中 accept() 工作,然后没有。
任何 help/advice 不胜感激。
您需要将 addr_len
初始化为 addr
的大小。
如果您查看 accept 的联机帮助页,在列出的 errno
值下; EINVAL
如果 addrlen
无效(例如负数)
(吹嘘):这不是相同的论点。
您正在调用 malloc()
,这可能 return 未初始化内存。
无论您设置什么值addrlen
可以将地址的多少字节复制到地址中; 0 表示 none.
我正在编写我认为是简单的 C 套接字程序的代码。该代码将充当原始服务器。它需要创建一个监听套接字,然后每次联系时,它需要accept()传入的连接,然后衍生出一个线程来处理一些基本的处理。我或多或少的线程和处理部分在工作,但是 accept() 部分在代码成功处理一些初始连接后出现故障。这是一个问题,因为我预计该程序将需要 运行 持续运行,并且可能必须处理大量传入请求。
首先是一些环境方面的东西:我正在开发一个 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#
我的 main() 函数设置一个监听套接字,然后开始一个无限循环。对于进入的每个连接,它都会尝试 accept() 然后将工作传递给分离的线程:
int main(int argc, char ** argv)
{
int sock = -1;
struct sockaddr_in address;
int port = 12345;
connection_t* connection;
pthread_t thread;
// Create the listening socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock <= 0){
fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
return -3;
}
// Bind socket to port
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0){
fprintf(stderr, "%s: error: cannot bind socket to port %d\n", argv[0], port);
return -4;
}
// Listen on the port
if (listen(sock, 5) < 0){
fprintf(stderr, "%s: error: cannot listen on port\n", argv[0]);
return -5;
}
// Listen forever...
while (1){
// Accept incoming connections
connection = (connection_t *)malloc(sizeof(connection_t));
printf("1) [[ sock: %d -- address: %s -- addr_len: %d ]]\n", connection->sock, &connection->address.sa_data, connection->addr_len );
connection->sock = accept(sock, &connection->address, &connection->addr_len);
printf("2) [[ sock: %d -- address: %s -- addr_len: %d ]]\n", connection->sock, &connection->address.sa_data, connection->addr_len );
if (connection->sock <= 0){
printf(" *** PROBLEM!!! Value of errno: %d\n ", errno);
free(connection);
}
else{
// Start a new thread but do not wait for it
pthread_create(&thread, 0, process, (void *)connection); // process() omitted
pthread_detach(thread);
}
}
return 0;
}
漂亮的教科书内容。当只有一个传入连接时,我制定了所有逻辑并使一切正常工作。
但后来我开始进行压力测试,并立即意识到我遇到了问题。我编写了一个客户端程序,它连续发送 X 个测试请求。上面的服务器代码对于一些初始请求工作正常,但随后就崩溃了。这是输出:
root@ubuntu:/home/me/socketProject# ./server
*** 1) [[ sock: 18954128 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 7 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18970816 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 8 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18962080 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 9 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18962112 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 10 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18954064 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 11 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18954160 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 12 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18907120 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 13 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18950880 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 14 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18961856 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 15 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18957136 -- address: -- addr_len: 0 ]]
*** 2) [[ sock: 17 -- address: -- addr_len: 16 ]]
*** 1) [[ sock: 18957168 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
*** 2) [[ sock: -1 -- address: -- addr_len: -518793662 ]]
*** PROBLEM!!! Value of errno: 22
*** 1) [[ sock: 18961856 -- address: -- addr_len: -518793662 ]]
你看到问题了。在上面的例子中,大约十次成功请求后发生了一些事情,然后 accept() 开始抱怨 ERRNO 22。快速 Google 搜索显示 ERRNO 22 是“EINVAL:无效参数”,这显然不好。
我从学生时代开始就做过一些简单的套接字编程,但我以前从未遇到过 accept() 的问题。我真的很纳闷。在我看来,N-1 个请求到达并被 accept() 成功处理。但随后第 N 次出现,accept() 不喜欢它,套接字被破坏。怎么样,为什么,我不知道。
accept() 正在抱怨 "invalid argument(s)"。但是客户端实际上是一遍又一遍地发送完全相同的测试消息。 N-1 连接如何提供有效参数,但第 N、N+1、N+2... 参数无效?这让我大吃一惊。
一些观察:
这是非黑即白的现象。我的意思是 套接字在 100% 的时间里都能正常工作,但随后出现了一些问题 accept() 发生,然后套接字再也无法工作。
我测试了运行很多次,不知道有多少成功 当我开始一个新的测试时,我会得到连接。我有多达 88 个 在套接字停止工作之前成功连接。在另一个 测试,在套接字打开之前我只有 2 个成功的连接 肚皮。之前的平均成功连接数 插座断裂大约为 17.
我的客户端测试程序没有尝试 space 发出请求 发送;它只是打开一个套接字并开始轰炸我的服务器 以最快的速度编程。我这样做是因为我想进行压力测试。 但也许我的客户端程序发送测试请求的速度太快了 服务器跟上……?
我想也有可能是客户端程序导致 问题。我不这么认为,因为它只是发送相同的测试 消息一遍又一遍,它永远不会抛出错误。
有没有人见过这样的问题?我一直在寻找 SO 大约一个小时,但我找不到另一个 post 其中 accept() 工作,然后没有。
任何 help/advice 不胜感激。
您需要将 addr_len
初始化为 addr
的大小。
如果您查看 accept 的联机帮助页,在列出的 errno
值下; EINVAL
如果 addrlen
无效(例如负数)
(吹嘘):这不是相同的论点。
您正在调用 malloc()
,这可能 return 未初始化内存。
无论您设置什么值addrlen
可以将地址的多少字节复制到地址中; 0 表示 none.