c++ - Tcp Client 发送的数据接收速度非常慢

标签 c++ linux tcp tcpclient tcpserver

我要做的系统有一台tcp服务器和大约1000个tcp客户端。 每秒有1000个客户端向tcp服务器发送数据。 为了模拟这种情况,首先我使用以下代码从一台PC连接到具有50个套接字的tcp服务器。

int main() {

    const char *hello = "Hello from client";

    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);
    serv_addr.sin_addr.s_addr = inet_addr("192.168.1.39");

    vector<int> vec;


    for ( uint8_t i = 0; i < 50; i++ ) {

        int sock =  socket(AF_INET, SOCK_STREAM, 0);
        if ( sock < 0 ) {
            cout << "... Cant Allocated Socket\n";
            return -1;
        }

        if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
        {
            cout << "... Connection Failed \n";
            return -1;
        }



        vec.push_back(sock);
    }

    for ( uint8_t i = 0; i < vec.size(); i++ ) {
        send(vec[i], hello, strlen(hello), 0);
        cout << "Message Send\n";
    }


    for ( uint8_t i = 0; i < vec.size(); i++ ) {
        shutdown(vec[i], 0);
        close(vec[i]);
    }
    return 0;
}

tcp客户端连接到tcp服务器后,将数据发送到tcp服务器并关闭套接字。我可以从终端看到tcp客户端可以发送数据包而无需等待(小于10ms)

上面的tcp客户端代码可以成功运行并成功将数据发送到tcp服务器。 我使用下面的 tcp 服务器代码显示来自 tcp 客户端的数据。

#define _DEF_TCP_SERVER_PORT                                        8080
#define _DEF_TCP_SERVER_MAX_QUEUE_LISTEN                            12

bool finish_app = false;

struct TcpClient {
    int clientSocket;
    struct in_addr clientAddr;
};
vector<TcpClient> TcpClients;


struct _ServiceTcpServer {
    bool enable;
    int sock;
    uint16_t connectedClient;
    uint32_t sockLen;
    sockaddr_in tcpServerAddr;
    sockaddr_in remoteAddr;
};

struct _ServiceTcpServer _serviceTcpServer;


void init_tcp_server_socket() {

    _serviceTcpServer.tcpServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    _serviceTcpServer.tcpServerAddr.sin_family = AF_INET;
    _serviceTcpServer.tcpServerAddr.sin_port = htons(_DEF_TCP_SERVER_PORT);
    _serviceTcpServer.sockLen = sizeof(_serviceTcpServer.remoteAddr);

    int flag = 1;

    for ( ;; ) {
        _serviceTcpServer.sock = socket(AF_INET, SOCK_STREAM, 0);
        if ( _serviceTcpServer.sock < 0 ) {
            cout << "... Failed to allocate socket.\n";
            this_thread::sleep_for(chrono::seconds(1));
            continue;
        }

        if ( setsockopt(_serviceTcpServer.sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) ) {
            cout << "... Set SockOpt failed.\n";
            close(_serviceTcpServer.sock);
            this_thread::sleep_for(chrono::seconds(1));
            continue;
        }

        if( bind(_serviceTcpServer.sock, (sockaddr *) &_serviceTcpServer.tcpServerAddr, sizeof(_serviceTcpServer.tcpServerAddr)) == -1 ) {
            cout << "... Socket bind failed.\n";
            close(_serviceTcpServer.sock);
            this_thread::sleep_for(chrono::seconds(1));
            continue;
        }

        if ( listen(_serviceTcpServer.sock, _DEF_TCP_SERVER_MAX_QUEUE_LISTEN) != 0 ) {
            cout << "... Socket listen failed.\n";
            close(_serviceTcpServer.sock);
            this_thread::sleep_for(chrono::seconds(1));
            continue;
        }

        break;

    }


    cout << "Socket init done \n";
}

void tcp_user_accept_task() {

    while ( finish_app == false ) {
        int temp_sck = -1;
        temp_sck = accept(_serviceTcpServer.sock, (sockaddr *) &_serviceTcpServer.remoteAddr, &_serviceTcpServer.sockLen);
        if ( temp_sck == -1 ) {
            this_thread::sleep_for(chrono::seconds(2));
            continue;
        }
        TcpClient tcpClient;
        tcpClient.clientAddr = _serviceTcpServer.remoteAddr.sin_addr;
        tcpClient.clientSocket = temp_sck;
        TcpClients.push_back( tcpClient );
        cout << "... New connection request: " << temp_sck << endl;
        ++_serviceTcpServer.connectedClient;
        this_thread::sleep_for(chrono::milliseconds(50));
    }
}


uint8_t temp_recv[100];
void tcp_server_run() {

    while ( finish_app == false ) {

        for(uint16_t i = 0 ; i < _serviceTcpServer.connectedClient; i++ ) {
            int temp_cs = TcpClients[i].clientSocket;
            fcntl(temp_cs, F_SETFL, O_NONBLOCK);
            int temp_recvLen  = recv(temp_cs, temp_recv, 20, 0);
            if( temp_recvLen > 0 ) {
                time_t _time = chrono::system_clock::to_time_t(chrono::system_clock::now());
                cout << "Message Received At:" << ctime(&_time) << "   :";
                cout << temp_recv << endl;
                break;
            } else {
                this_thread::sleep_for(chrono::milliseconds(10));
            }
        }

        if ( temp_recv[0] == 'q' ) {
            finish_app = true;
        }
    }

    close(_serviceTcpServer.sock);
}




int main() {

    thread init_thread(init_tcp_server_socket);
    init_thread.join();
    thread accept_thread(tcp_user_accept_task);
    thread run_thread(tcp_server_run);
    accept_thread.join();
    run_thread.join();

    return 0;
}

但问题是,如屏幕图像所示,仅 1 秒内就收到了 3-4 个数据包。

enter image description here

注意: 当代码this_thread::sleep_for(chrono::milliseconds(10));评论了,问题解决了。但由于处理器未处于 sleep 状态,因此处理器正以 100% 的速度工作。 当客户端被接受时,我使用下面的代码向客户端接收添加了 10 us 超时并注释和 fcntl(temp_cs, F_SETFL, O_NONBLOCK);

struct timeval _timeval;
_timeval.tv_sec = 0;
_timeval.tv_usec = 10;
setsockopt(tcpClient.clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &_timeval, sizeof(_timeval));

问题仍然存在,如“this_thread::sleep_for”。

最佳答案

您应该同时接收套接字,而不是查询每个套接字并在每次数据尚未准备好时休眠 10 毫秒。

正确的方法取决于平台

  • posix - 选择

  • linux - poll、epoll、io_submit

  • Windows - I/O 完成端口

通常,选择 posix 标准就足以满足您的需求。 如果您想要多平台,您可能还想探索 3rd 方库,例如 libeventlibev,它们已经为您包装了这些平台相关调用。

祝你编码愉快!

关于c++ - Tcp Client 发送的数据接收速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60613865/

相关文章:

c++ - Qt:如何通过外部程序打开文件, "open with..."对话框

c++仿函数和函数模板

linux - 使用 bash 脚本更改文件名

node.js - 当logstash服务器断开连接时,nodejs中出现ECONNREFUSED错误

tcp - 在 PIC 微 Controller 中实现 MQTT

c++ - 在模板别名中解包参数包

c++ - 使用 boost::locale/ICU 边界分析与中文

PHP:测试两个双变量会在不更改变量的情况下给出不同的结果

html - 找不到 URL 错误,而它确实存在

python - 带有 Python : How to optimize my implementation? 的 TCP 服务器