Как отправить 2 TCP пакета в c ++ - PullRequest
0 голосов
/ 15 марта 2012

возможно ли отправить 2 последовательных TCP-пакета, как показано на этом рисунке: enter image description here

В настоящее время я установил для TCP_NODELAY значение true, а для SO_SNDBUF - 0. Я также вызвал функцию send в моей программе 2x,Вот результат, который я получил:

enter image description here

Основной проблемой здесь будет задержка подтверждения, вызывающая низкую производительность сети на втором снимке экрана.

Коддля сервера:

DWORD WINAPI ServerHandler(void *lp){
    //The port you want the server to listen on
    int host_port = 1852;

    //Initialize socket support WINDOWS ONLY!
    unsigned short wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 2, 2 );
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )) 
    {
        printf("Could not find useable sock dll %d\n",WSAGetLastError());
        return 0;
    }

    //Initialize sockets and set any options
    int hsock;
    BOOL bOptVal = true;
    int bOptLen = sizeof (BOOL);
    int iResult = 0;

    hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(hsock == INVALID_SOCKET)
    {
        printf("Error initializing socket %d\n",WSAGetLastError());
        return 0;
    }

    iResult = setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char *) &bOptVal, bOptLen);
    if (iResult == SOCKET_ERROR)
        printf("setsockopt for SO_REUSEADDR failed with error: %d\n", WSAGetLastError());
    else
        printf("Set SO_REUSEADDR: ON\n");

    iResult = setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char *) &bOptVal, bOptLen);
    if (iResult == SOCKET_ERROR)
        printf("setsockopt for SO_KEEPALIVE failed with error: %d\n", WSAGetLastError());
    else
        printf("Set SO_KEEPALIVE: ON\n");

    //Bind and listen
    struct sockaddr_in my_addr;

    my_addr.sin_family = AF_INET ;
    my_addr.sin_port = htons(host_port);

    memset(&(my_addr.sin_zero), 0, 8);
    my_addr.sin_addr.s_addr = INADDR_ANY ;

    if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == SOCKET_ERROR )
    {
        printf("Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
        closesocket(hsock);
        return 0;
    }
    if( listen( hsock, MAXCONN) == SOCKET_ERROR )
    {
        printf("Error listening %d\n",WSAGetLastError());
        closesocket(hsock);
        return 0;
    }

    //Now lets to the server stuff

    int* csock;
    sockaddr_in sadr;
    int addr_size = sizeof(SOCKADDR);

    printf("waiting for a connection\n");

    while(true)
    {            
        csock = (int*)malloc(sizeof(int));
        if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET )
        {
            printf("Received connection from %s, %u @ socket %d\n", inet_ntoa(sadr.sin_addr), sadr.sin_port, *csock);

            BOOL bOptVal = true;            
            int iResult = setsockopt(*csock, SOL_SOCKET, TCP_NODELAY, (char *) &bOptVal, sizeof(bOptVal));
            if (iResult == SOCKET_ERROR)
                printf("setsockopt for TCP_NODELAY failed with error: %d\n", WSAGetLastError());
            else
                printf("Set TCP_NODELAY: TRUE\n");

            int sendBuf = 0;
            iResult = setsockopt(*csock, SOL_SOCKET, SO_SNDBUF, (char *) &sendBuf, sizeof(sendBuf));
            if (iResult == SOCKET_ERROR)
                printf("setsockopt for SO_SNDBUF failed with error: %d\n", WSAGetLastError());
            else
                printf("Setsockopt for SO_SNDBUF set to 0\n");


            CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
        }
        else
        {
            printf("Error accepting %d\n",WSAGetLastError());
        }
    }
    WSACleanup();
}

Код, который я использовал для отправки данных:

int send_TCP_2(int cs, char responseLength[], char data[], int respond_length, int data_length)
{   
    int size = respond_length + data_length;
    int index = 0;

    // combined 10 byte response with data as 1 packet
    std::vector<char> packet(size);

    for(int i=0; i<respond_length; i++)
    {
        packet[index] = responseLength[i];
        index++;
    }

    for(int i=0; i<data_length; i++)
    {
        packet[index] = data[i];
        index++;
    }

    int status;
    char *data_ptr = &packet[0];
    while(size > 0)
    {
        status = send(cs, data_ptr, size, 0);
        if(status > 0)
        {
            data_ptr += status;
            size -= status;
        }
        else if (status == SOCKET_ERROR)
        {
            int error_code = WSAGetLastError();
            printf("send_TCP_2 failed with error code: %d\n", error_code);
            return 0;   // send failed
        }
    }
    return 1;   // send successful  
}

enter image description here

Я прикрепил скриншот, когда не отключаю Nagleи не трогать SO_SNDBUF.

Ответы [ 3 ]

3 голосов
/ 15 марта 2012

Основной проблемой здесь будет задержка подтверждения, вызывающая низкую производительность сети на втором снимке экрана.

Нет, не будет.Вы ошибаетесь по этому поводу.Вы не имеете никакого контроля над пакетированием TCP или, вернее, сегментацией, и вам это не нужно.TCP - высокооптимизированный протокол передачи потоков, разработанный более 30 лет назад.

0 голосов
/ 19 марта 2012

спасибо за все советы! Установка для TCP_NODELAY значения true будет работать, как упоминалось большинством. Я сделал глупую ошибку в setsockopt!

Я должен был поставить IPPROTO_TCP вместо SOL_SOCKET

0 голосов
/ 15 марта 2012

TCP_NODELAY option set to TRUE должен исправить проблему delayed_ACK. Мне когда-то приходилось отправлять сетевой пакет дважды, но я делал это в ETHERNET (driver) layer, и он работал там (задержка_ACK была вызвана другой стороной), но на этом уровне (уровень SOCKET) вы не можете сделать такую ​​вещь. Также не устанавливайте SO_SNDBUF в 0 ...

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