加速非阻塞Unix套接字(C ++)

时间:2009-06-25 03:02:50

标签: c++ select sockets delay nonblocking

我实现了一个简单的套接字包装类。它包括一个非阻塞函数:

void Socket::set_non_blocking(const bool b) {
    mNonBlocking = b; // class member for reference elsewhere
    int opts = fcntl(m_sock, F_GETFL);
    if(opts < 0) return;
    if(b)
        opts |= O_NONBLOCK;
    else
        opts &= ~O_NONBLOCK;

    fcntl(m_sock, F_SETFL, opts);
}

该类还包含一个简单的接收函数:

int Socket::recv(std::string& s) const {
    char buffer[MAXRECV + 1];
    s = "";
    memset(buffer,0,MAXRECV+1);
    int status = ::recv(m_sock, buffer, MAXRECV,0);

    if(status == -1) {
    if(!mNonBlocking)
        std::cout << "Socket, error receiving data\n";

        return 0;
    } else if (status == 0) {
        return 0;
    } else {
        s = buffer;
        return status;
    }
}

实际上,调用Socket :: recv()时似乎有~15ms的延迟。这种延迟是否可以避免?我已经看到一些使用select()的非阻塞示例,但不明白这可能会有什么帮助。

4 个答案:

答案 0 :(得分:1)

这取决于你如何使用套接字。如果您有多个套接字并且遍历所有套接字,则检查可能导致延迟的数据。

使用非阻塞recv,你取决于那里的数据。如果您的应用程序需要使用多个套接字,则必须不断地轮流汇集每个套接字以查明是否有任何数据可用。

这对系统资源不利,因为这意味着即使无事可做,您的应用程序也会持续运行。

你可以用select来避免这种情况。您基本上设置了套接字,将它们添加到组并在组上进行选择。当任何选定套接字上发生任何事情时,select返回指定发生了什么以及在哪个套接字上。

有关如何使用select beej's guide to network programming

的一些代码

答案 1 :(得分:0)

select将允许您指定超时,并可以测试套接字是否可以读取。所以你可以使用小于15ms的东西。顺便提一下,如果线上的数据可能包含嵌入的NUL,则需要小心使用该代码,否则将不包含所有读取的数据。您应该使用类似s.assign(buffer, status);的内容。

答案 2 :(得分:0)

除了stefanB之外,我发现你每次都在调整你的缓冲区。何必? recv返回实际读取的字节数。只需将(缓冲区[status + 1] = NULL)

后的一个字节清零

答案 3 :(得分:0)

你的MAXRECV有多大?可能只是因为您在堆栈增长时出现页面错误。其他人已经提到将接收缓冲区归零是完全没必要的。当您从收到的字符数据中创建std::string时,您还可以进行内存分配和复制命中。