Cara mengirim 2 paket TCP di c++

apakah mungkin untuk mengirim 2 paket TCP berturut-turut seperti yang terlihat pada gambar di sini: masukkan deskripsi gambar di sini

Saat ini saya telah menyetel TCP_NODELAY ke true dan SO_SNDBUF ke 0. Saya juga memanggil send di program saya 2x. Inilah hasil yang saya peroleh:

masukkan deskripsi gambar di sini

Masalah utama di sini adalah penundaan ack yang menyebabkan kinerja jaringan lambat pada tangkapan layar ke-2.

Kode untuk servernya:

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();
}

Kode yang saya gunakan untuk mengirim data:

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  
}

masukkan deskripsi gambar di sini

Saya telah melampirkan tangkapan layar ketika saya tidak menonaktifkan Nagle dan tidak menyentuh SO_SNDBUF.


person user990639    schedule 15.03.2012    source sumber
comment
Apa yang membuat Anda berpikir bahwa ukuran paket (dan bukan faktor lainnya) mempengaruhi kinerja jaringan? Apakah kedua tangkapan layar tersebut berasal dari pasangan komputer yang sama di jaringan yang sama?   -  person Adam Liss    schedule 15.03.2012
comment
TCP_NODELAY seharusnya cukup di sini.   -  person Nikolai Fetissov    schedule 15.03.2012
comment
@AdamLiss Oh tidak, saya tidak mengatakan bahwa ukuran paket mempengaruhi jaringan. Saya mencoba mengeluarkan 2 paket secara berurutan untuk mendapatkan ACK segera. Ini akan menghilangkan penundaan 200 ms yang terlihat pada gambar ke-2. (0,011 hingga 0,210)   -  person user990639    schedule 15.03.2012
comment
Menurut Anda, dalam hal apa ack tertunda menyebabkan kinerja jaringan lambat? Tumpukan TCP pengirim tidak perlu menunggu untuk mendapatkan ack yang tertunda sebelum mengirimkan pernyataan berikutnya.   -  person Kaz    schedule 15.03.2012
comment
TCP adalah protokol jendela geser, bukan protokol stop-and-wait.   -  person Kaz    schedule 15.03.2012
comment
@NikolaiNFetissov Saya telah mengaktifkan TCP_NODELAY di soket klien.   -  person user990639    schedule 15.03.2012
comment
Juga, dari man 7 socket di Linux: `SO_SNDBUF Mengatur atau mendapatkan buffer pengiriman soket maksimum dalam byte. Kernel menggandakan nilai ini (untuk memberikan ruang untuk overhead pembukuan) ketika diatur menggunakan setockopt(2), dan nilai ganda ini dikembalikan oleh getockopt(2). Nilai default ditetapkan oleh file /proc/sys/net/core/wmem_default dan nilai maksimum yang diizinkan ditetapkan oleh file /proc/sys/net/core/wmem_max. Nilai minimum (dua kali lipat) untuk opsi ini adalah 2048.   -  person Kaz    schedule 15.03.2012
comment
Yaitu. pengaturan SO_SNDBUF ke 0 mungkin tidak berfungsi di semua tempat. Apakah itu didokumentasikan pada OS yang Anda gunakan?   -  person Kaz    schedule 15.03.2012
comment
@Kaz Saya tidak terlalu yakin tentang TCP tetapi mengapa server segera mengirimkan (waktu 0,221) paket berikutnya tepat setelah klien mengirimkan ACK-nya (waktu 0,210)?   -  person user990639    schedule 15.03.2012
comment
mari kita melanjutkan diskusi ini di chat   -  person user990639    schedule 15.03.2012
comment
Seperti yang dikatakan orang lain, TCP_NODELAY harus menjadi apa yang Anda cari untuk memungkinkan transmisi bolak-balik. Jika itu tidak berhasil untuk Anda, Anda mungkin salah melakukannya. Bisakah kita melihat beberapa kode?   -  person Guy Sirton    schedule 15.03.2012
comment
@GuySirton Saya telah melampirkan kode server yang menunjukkan di mana saya mengatur TCP_NODELAY dan SO_SNDBUF.   -  person user990639    schedule 15.03.2012
comment
Hapus semua perubahan pengaturan Anda. Lalu, uji lagi. Jika Anda mempunyai masalah kinerja, posting jejaknya sehingga kami dapat mengetahui apa yang salah. Namun dengan pesimistis tumpukan tersebut, Anda menciptakan masalah yang Anda lihat dan menghancurkan harapan untuk menemukan dan memperbaikinya. (Kemungkinan besar, masalah yang Anda alami sekarang disebabkan oleh penulisan kecil, Nagle dinonaktifkan, dan buffer kecil. Ini semua adalah masalah yang Anda buat.)   -  person David Schwartz    schedule 15.03.2012
comment
@DavidSchwartz Saya memahami masalah yang muncul ketika saya melakukan pengiriman ukuran kecil dan menonaktifkan Nagle dan bahkan membuat buffer pengiriman 0. Namun, saya tertarik pada bagaimana server lain dapat mengirimkan paket berukuran lebih kecil dan pada waktu yang lebih cepat dibandingkan dengan milik saya . Karena dari apa yang saya lihat pada gambar pertama, server mampu mengirimkan paket individual sebesar 206 byte. Saya telah mencoba menonaktifkan Nagle dan yang saya lihat adalah beberapa paket masih menyatu menjadi ukuran paket yang lebih besar.   -  person user990639    schedule 15.03.2012
comment
@ user990639: Anda tidak akan dapat mengetahui semua perubahan pengaturan yang telah Anda lakukan yang membuat kinerja menjadi buruk. Lakukan segalanya dengan benar lalu perbaiki masalah kinerja apa pun yang Anda alami. Segala sesuatu yang Anda lakukan sejauh ini membuat kinerja menjadi buruk, jadi tidak mengherankan jika kinerja Anda buruk. Aktifkan Nagle. Kirim data sebanyak mungkin dalam setiap panggilan. Jangan mengecilkan buffer. Lalu, jika Anda mengalami masalah kinerja, kami dapat membantu Anda menemukan dan memperbaikinya.   -  person David Schwartz    schedule 15.03.2012


Jawaban (3)


Masalah utama di sini adalah penundaan ack yang menyebabkan kinerja jaringan lambat pada tangkapan layar ke-2.

Tidak, itu tidak akan terjadi. Anda salah tentang hal itu. Anda tidak memiliki kendali atas paketisasi TCP, atau lebih tepatnya segmentasi, dan Anda tidak memerlukannya. TCP adalah protokol transfer aliran yang sangat optimal yang dikembangkan selama lebih dari 30 tahun.

person user207421    schedule 15.03.2012
comment
+1.000 Anda mencoba memperbaiki sesuatu yang tidak rusak. Paling-paling, Anda tidak akan merusaknya. (Namun, kemungkinan besar, Anda akan merusaknya dengan memaksakan penulisan kecil.) - person David Schwartz; 15.03.2012
comment
TCP tidak sempurna. TCP adalah palu yang kami miliki, jadi kami terus memasang sekrup ke dinding. Untuk komunikasi permintaan/respon, TCP memiliki kekurangan yang menonjol, terutama yang berkaitan dengan windowing. Ada banyak diskusi di web tentang kelemahan skema windowing TCP sehubungan dengan kecenderungan HTTP modern untuk membuka banyak koneksi TCP. - person Dave Dopson; 18.05.2012

TCP_NODELAY option set to TRUE harus memperbaiki masalah tertunda_ACK. Saya pernah harus mengirim paket jaringan dua kali tetapi saya melakukannya di ETHERNET (driver) layer dan berhasil di sana (delayed_ACK disebabkan oleh pihak lain), tetapi di lapisan ini (lapisan SOCKET) Anda tidak dapat melakukan hal seperti itu. Juga, jangan setel SO_SNDBUF ke 0...

person Malkocoglu    schedule 15.03.2012

terima kasih atas semua sarannya! Menyetel TCP_NODELAY ke true akan berfungsi seperti yang disebutkan oleh sebagian besar orang. Saya telah membuat kesalahan konyol di setockopt!

Saya seharusnya memasukkan IPPROTO_TCP daripada SOL_SOCKET

person user990639    schedule 19.03.2012