Tcp-пакеты, отправленные сокетом через send (), медленные - PullRequest
0 голосов
/ 24 ноября 2018

Я пытаюсь написать приложение на C / C ++, связывающееся с устройством с использованием сокета tcp.Мое приложение действует как сокет сервера.При получении данных от сокета устройства сервер отвечает на устройство с помощью функции send ():

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

Длина буфера (~ 4 КБ) больше, чем MTU (1500 байт).TCP делит его на более мелкие пакеты.Я использовал wireshark для захвата пакетов.Я видел, что задержка между пакетами tcp составляет 0,2-0,3 с.Если я отправляю большие данные (~ 100 МБ), это занимает слишком много времени (несколько часов).Я пытался установить setsockopt для включения TCP_NODELAY, TCP_QUICKACK и TCP_CORK, но все еще не могу уменьшить задержку.Не могли бы вы, ребята, помочь мне в этом вопросе?-------------------РЕДАКТИРОВАТЬ: Вот мой код:

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

void createServerSocket();
void acceptConnect(int serverSock);
void receiveDataFromSocket(int socket);
void sendDataOverSocket(int clientSock);

void createServerSocket() {
    int serverSockFd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    std::string address = "fd53:7cb8:383:5::68";
    int port = 42654;

    if (serverSockFd < 0)
    {
        printf("Create Server socket fail");
        return;
    }
    struct sockaddr_in6 serverAddress;
    (void)memset(&serverAddress, 0, sizeof(sockaddr_in6));
    serverAddress.sin6_family = AF_INET6;
    serverAddress.sin6_port = htons(port);
    int result = inet_pton(AF_INET6, address.c_str(), &serverAddress.sin6_addr);

    if (result <= 0)
    {
        printf("inet_pton() failed portnumber: %d, address: %s \n", port, address.c_str());
        return;
    }

    // setting socket options
    int flag = 1;

    if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_QUICKACK  ,(char *)&flag,sizeof(flag)) == -1)
    {
        printf("setsockopt TCP_QUICKACK failed for server socket on address %s \n", address.c_str());
    }
    if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_CORK,(char *)&flag,sizeof(flag)) == -1)
    {
        printf("setsockopt TCP_CORK failed for server socket on address %s \n", address.c_str());
    }
    if(setsockopt(serverSockFd,IPPROTO_TCP,TCP_NODELAY,(char *)&flag,sizeof(flag)) == -1)
    {
        printf("setsockopt TCP_NODELAY failed for server socket on address %s \n", address.c_str());
    }

    result = bind(serverSockFd, (struct sockaddr*)&serverAddress, sizeof(sockaddr_in6));

    if (result != 0)
    {
        printf("bind() failed portnumber: %d, address: %s \n", port, address.c_str());
        return ;
    }

    result = listen(serverSockFd, 10);
    if (result != 0) {
        printf("listen() failed portnumber: %d, address: %s \n", port, address.c_str());
        return ;
    }

    acceptConnect(serverSockFd);
}

void acceptConnect(int serverSock)
{
    struct sockaddr_in6 clientAddress;
    socklen_t len = sizeof(sockaddr_in6);
    memset(&clientAddress, 0, sizeof(sockaddr_in6));

    const int clientSocket = accept(serverSock, (struct sockaddr*)&clientAddress, &len);

    if(clientSocket >= 0) {
        char str_addr[INET6_ADDRSTRLEN];
        inet_ntop(AF_INET6, &(clientAddress.sin6_addr),
                  str_addr, sizeof(str_addr));
        printf("New connection from: %s:%d ...\n", str_addr, ntohs(clientAddress.sin6_port));
        receiveDataFromSocket(clientSocket);
    }
}

void receiveDataFromSocket(int socket)
{
    int SOCKET_BUFFER_MAX_SIZE = 8*1024;

    char buffer[SOCKET_BUFFER_MAX_SIZE];
    memset(buffer, '\0', SOCKET_BUFFER_MAX_SIZE);
    //Receive data from sock
    while (true) {
        int dataLen = recv(socket, buffer, SOCKET_BUFFER_MAX_SIZE, 0);
        printf("Receive data from socket: %d, msgLength = %d\n", socket, dataLen);
        sendDataOverSocket(socket);
    }
}

void sendDataOverSocket(int clientSock)
{
    int dataLen = 4*1024 + 7;
    char *buf = new char[dataLen];
    memset(buf, 'a', 4*1024 + 7);
    int ret;
    ret = send(clientSock, buf, dataLen, 0);

    if (ret <= 0) {
        printf("ERROR Send message over socket");
        return;
    }

    int error_code;
    socklen_t error_code_size = sizeof(sockaddr_in6);
    getsockopt(clientSock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_size);
    printf("Error code size: %d, error code: %d\n", error_code_size, error_code);
}

1 Ответ

0 голосов
/ 29 ноября 2018

Я думаю, что вы превышаете буферы отправки TCP, вы последовательно получаете и отправляете, если другая сторона недостаточно быстро читает данные из сокета, вы будете ждать в каждой операции send (), пока у вас не будет места в буфере отправки.

Проверьте, отправляете ли вы больше информации, чем получаете, я подозреваю, что recv () читает небольшие блоки (потому что MTU), но вы отправляете около 4 КБ в каждом цикле, поэтому ваши вызовы recv / send не выполняются должным образомсбалансированный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...