Проблема с сокетом под C ++ - PullRequest
0 голосов
/ 31 июля 2009

Я открыл соединение с сервером следующим образом

SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(445);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr);

// Attempt to connect to server
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0)
{
    printf("Failed to establish connection with server\r\n");
    WSACleanup();
    system("PAUSE");
    return 0;
}

Затем я пытаюсь отправить данные по TCP-соединению следующим образом:

unsigned char completePacket[100] = something;

send(Socket, (char *) completePacket, 100, 0);

Это нормально работает 2 раза, но в третий раз кажется, что пакет не отправлен ... Нужно ли сбрасывать носки после каждой отправки или как-то их сбрасывать?

Спасибо

Ответы [ 4 ]

3 голосов
/ 01 августа 2009

При частой отправке небольшого объема данных стек TCP / IP буферизует данные в соответствии с алгоритмом управления потоком. Это для оптимального использования полосы пропускания. Это называется алгоритм Нейгла. Ваши наблюдения, скорее всего, связаны с тем, что алгоритм Nagle включен (включен по умолчанию). Но это может быть что-то совсем другое. Вы можете убедиться в процессе устранения следующим образом.

Поставьте следующий код после connect

int flag = 1;
int result = setsockopt(sock,            
                 IPPROTO_TCP,
                 TCP_NODELAY,
                 (char *) &flag,
                 sizeof(flag));
if (result < 0)
... handle the error ...

Если вы не видите никакой разницы в ваших результатах, ваша проблема не в механизме управления потоком по умолчанию.

3 голосов
/ 31 июля 2009
send(Socket, (char *) completePacket, 100, 0);

Хорошо, но вы должны всегда проверять возвращаемое значение. send может на самом деле отправлять меньше, чем вы говорите (маловероятно, что это проблема, когда вы отправили всего 300 байт.)

Вам не нужно очищать сокет.

Может проблема в приемнике? Помните, что TCP предоставляет поток, а не пакеты или сообщения. Для одного вызова может потребоваться несколько вызовов recv, чтобы получить их все. И данные, отправленные несколькими вызовами отправки, могут быть получены только за один вызов recv. Вы должны отслеживать, сколько данных вы получили.

Если вы хотите проверить, какие данные передаются по сети, установите сетевой монитор, например Wireshark.

2 голосов
/ 31 июля 2009

Если другая сторона не подтверждает пакет перед отправкой следующего, то дополнительные пакеты могут быть задержаны из-за алгоритма Нейгла , указанного в RFC 896 . По сути, дальнейшие небольшие посылки будут буферизироваться и отправляться в одном более крупном пакете, как только подтвержденные данные, которые уже были отправлены, будут подтверждены. Это помогает предотвратить переполнение сети множеством небольших пакетов.

1 голос
/ 31 июля 2009

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

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