C Programming::accept() 在压力测试中工作然后不工作

标签 c sockets 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#

我的 ma​​in() 函数设置一个监听套接字,然后开始一个无限循环。对于进入的每个连接,它都会尝试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。快速谷歌搜索显示,ERRNO 22 是“EINVAL: Invalid argument”,这显然不好。

我从学生时代开始就做过一些简单的套接字编程,但我以前从未遇到过 accept() 的问题。我真的很纳闷。在我看来,N-1 个请求到达并被 accept() 成功处理。但是随后出现第 N 个,accept() 不喜欢它,并且套接字被损坏。如何或为什么,我不知道。

accept() 提示“无效参数”。但是客户端实际上是一遍又一遍地发送完全相同的测试消息。 N-1 连接如何提供有效参数,但第 N、N+1、N+2... 参数无效?这让我大吃一惊。

一些观察:

  • 这是一个非黑即白的现象。我的意思是 套接字在 100% 的时间里都能正常工作,但随后出现了一些问题 发生在 accept() 时,然后套接字再也无法工作。

  • 我进行了很多测试,不知道有多少成功 当我开始一个新的测试时,我会得到连接。我有多达 88 个 在套接字停止工作之前成功连接。在另一个 测试,在套接字打开之前我只有 2 个成功的连接 肚皮。之前的平均成功连接数 socket 断裂约为 17 个。

  • 我的客户端测试程序不会尝试将请求隔开 发送;它只是打开一个套接字并开始轰炸我的服务器 以最快的速度编程。我这样做是因为我想进行压力测试。 但也许我的客户端程序发送测试请求的速度太快了 服务器跟上……?

  • 我想,也有可能是客户端程序导致 问题。我不这么认为,因为它只是发送相同的测试 一遍又一遍地发送消息,它永远不会抛出错误。

有没有人见过这样的问题?我已经在 SO 上找了大约一个小时,但我找不到另一篇 accept() 起作用的帖子,然后又不起作用。

感谢任何帮助/建议。

最佳答案

您需要将addr_len 初始化为addr 的大小。

如果您查看 accept 的联机帮助页,在列出的 errno 值下; EINVAL 如果 addrlen 无效(例如为负数)

(吹嘘):这不是相同的论点。

您正在调用可能会返回未初始化内存的 malloc()

无论您将 addrlen 设置为多少字节的地址都可以复制到 address 中; 0 表示没有。

关于C Programming::accept() 在压力测试中工作然后不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57981377/

相关文章:

将指针转换为固定大小的数组

C函数返回正确结果但没有给出return语句,为什么?

C语言yes or no if语句带char?

c - 无法从 C 中的 HTTP 请求获取路径和方法

ruby-on-rails - Ruby on Rails 4 中的压力测试

c++ - 防止 overdraw 的技术(OpenGL)

java序列化套接字输入流刷新

java - Java Swing Socket 中的数据丢失

python - 可编写脚本的 HTTP 基准测试(最好在 Python 中使用)

JMeter 和 JavaScript