如何在c ++中发送2个TCP数据包

时间:2012-03-15 02:12:49

标签: c++ networking tcp

是否可以发送2个连续的TCP数据包,如下图所示:enter image description here

我目前已将TCP_NODELAY设置为true,SO_SNDBUF设置为0.我还在程序中调用了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 个答案:

答案 0 :(得分:3)

  

这里的主要问题是延迟ack导致网络速度慢   在第二个截图中表现。

不,不会。你错了。您无法控制TCP分组化,或者更确切地说是分段,并且您不需要它。 TCP是30多年来开发的高度优化的流传输协议。

答案 1 :(得分:0)

TCP_NODELAY option set to TRUE应修复delayed_ACK问题。我曾经不得不两次发送网络数据包,但我在ETHERNET (driver) layer做了它并且它在那里工作(delayed_ACK是由另一方引起的),但在这一层(SOCKET层)你不能做这样的事情。另外,不要将SO_SNDBUF设置为0 ...

答案 2 :(得分:0)

感谢所有的建议!将TCP_NODELAY设置为true将如大多数人所述。我在setsockopt中犯了一个愚蠢的错误!

我应该放 IPPROTO_TCP 而不是 SOL_SOCKET