C HTTP Server& OpenSSL - 适用于HTTP - 使用HTTPS删除多个/快速/并发连接

时间:2013-09-08 20:06:13

标签: c connection openssl httpserver

我正在使用套接字在C中编写HTTP服务器。它可以侦听多个端口,并以每个端口1个线程为基础运行侦听循环,每个循环生成另一个线程以提供响应

代码在提供标准HTTP响应时非常有效。我已将其设置为使用包含JavaScript代码的HTML页面进行响应,该代码仅重复刷新浏览器以便对服务器进行压力测试。我用我的计算机作为服务器进行了测试,其他4个设备同时向请求发送垃圾邮件。

没有崩溃,连接断开,没有内存泄漏。在HTTP模式下,2.0 GHz Intel Core 2 Duo上的CPU使用率从未超过5%,其中有4个设备发出垃圾邮件请求。

我昨天刚刚添加了OpenSSL,因此它可以通过HTTPS提供安全响应。这相当顺利,因为我似乎只需要用OSSL对应的安全模式替换一些标准套接字调用(基于这个问题的解决方案:Turn a simple socket into an SSL socket)。

每个连接有一个SSL上下文和SSL结构。它确实有效,但不是很可靠。同样,每个响应都在自己的线程上发生,但安全模式下的多个/快速/并发请求似乎随机丢弃,尽管我的代码中仍然没有崩溃或内存泄漏。

当连接断开时,浏览器会说它等待从未发生过的响应(Chrome)或只是说连接已重置(Firefox)。

作为参考,这里是更新的连接创建和关闭代码。

连接创建代码(监听循环的主要部分):

// Note:    sslCtx and sslConnection exist
//          elsewhere in memory allocated specifically
//          for each connection.

struct sockaddr_in clientAddr; // memset-ed to 0 before accept
int clientAddrLength = sizeof(clientAddr);

...

int clientSocketHandle = accept(serverSocketHandle, (struct sockaddr *)&clientAddr, &clientAddrLength);

...

if (useSSL)
{
    int use_cert, use_privateKey, accept_result; 

    sslCtx = SSL_CTX_new(SSLv23_server_method());
    SSL_CTX_set_options(sslCtx, SSL_OP_SINGLE_DH_USE);

    use_cert = SSL_CTX_use_certificate_file(sslCtx, sslCertificatePath , SSL_FILETYPE_PEM);
    use_privateKey = SSL_CTX_use_PrivateKey_file(sslCtx, sslCertificatePath , SSL_FILETYPE_PEM);

    sslConnection = SSL_new(sslCtx);
    SSL_set_fd(sslConnection, clientSocketHandle);

    accept_result = SSL_accept(sslConnection);
}

... // Do other things and spawn request handling thread

连接结束代码:

int recvResult = 0;

if (!useSSL)
{
    shutdown(clientSocketHandle, SHUT_WR);

    while (TRUE)
    {
        recvResult = recv(clientSocketHandle, NULL, 0, 0);
        if (recvResult <= 0) break;
    }
}
else
{
    SSL_shutdown(sslConnection);

    while (TRUE)
    {
        recvResult = SSL_read(sslConnection, NULL, 0);
        if (recvResult <= 0) break;
    }

    SSL_free(sslConnection);
    SSL_CTX_free(sslCtx);
}


closesocket(clientSocketHandle);

同样,这对HTTP响应非常有效。 HTTPS响应可能出现什么问题?

更新

我已经使用针对多线程环境的OpenSSL回调更新了代码,并且使用来自此问题的答案的代码,服务器更可靠:OpenSSL and multi-threads

我编写了一个小命令行程序,用HTTPS请求向服务器发送垃圾邮件,并且它不会丢弃与它同时运行的5个多个实例的任何连接。 Firefox的多个实例似乎也没有丢弃任何连接。

有趣的是,使用现代基于WebKit的浏览器仍然会删除连接。 Chrome在30秒内发送垃圾邮件时开始断开连接,iPhone 4(iOS 5.1)上的Safari在说连接丢失之前很少超过3次刷新,但iPad 2(iOS 5.0)上的Safari似乎应对时间最长但是最终也会失去联系。

1 个答案:

答案 0 :(得分:1)

您应该在请求处理线程中调用SSL_accept()。这将允许您的侦听线程更快地处理TCP接受/侦听队列,并减少由于完整的接受/侦听队列而新连接从TCP堆栈获得RESET的机会。

SSL握手是计算密集型的。我猜你的垃圾邮件发送者可能没有使用SSL会话缓存,因此这会导致您的服务器使用最大量的CPU。这将导致它在维修其他连接或新的传入连接时缺乏CPU。