Протокол Finger и информация о пользователях, страница 11

if (nCharSent == SOCKET_ERROR)

MessageBoxfNULL, "Error occurred during send()!", PROG_NAME,

MB_OK|MB_ICONSTOP) ;

else // Получаем информацию Finger от удаленного компьютера { do {

nCharRecv = recv(nSocket, (LPSTR)&szFingerInfo[nConnect],

sizeof(szFingerInfo) nConnect, RECV_FLAGS) ;

nConnect += nCharRecv;

} while (nCharRecv > 0);

Рассмотрим одно очень важное соображение относительно длины буфера принимаемых данных. Поскольку служба Finger использует потоковый протокол TCP, чтобы собрать все данные, нужно использовать цикл типа do-while. Даже если вы и назначите большой буфер, удаленный компьютер может просто не успеть передать все данные за один прием. Предположим, что вы запрашиваете информацию обо всех работающих в данный момент пользователях (посылая пустую строку-запрос). Допустим, что на компьютере в этот момент работает значительное число пользователей. Объем ответного сообщения сервера, наконец, может превышать значение MTU (блока данных максимальной длины) для вашей сети.

Чтобы не допустить фрагментации, TCP передает данные, разделив их на сегменты. То есть сокет может получить несколько сегментов TCP до того, как все данные будут переданы. Сервер Finger автоматически закрывает соединение после того, как все данные посланы. Функция recv, в свою очередь, опознает закрытие соединения и в ответ возвращает ноль. Другими словами, цикл do-while требуется, чтобы собрать все данные от сервера. Принятые данные хранятся в буфере szFingerInfo. Количество принятых символов подсчитывается при каждом вызове recv и помещается в переменную nCharRecv целого типа:

do {

nCharRecv = recv(nSocket, (LPSTR)&szFingerInfo[nConnect], sizeof(szFingerInfo) - nConnect, RECV_FLAGS) ;

nConnect += nCharRecv;

} while (nCharRecv > 0) ;

Переменная nConnect подсчитывает общее количество принятых в течение работы цикла символов следующим образом:

nConnect += nCharRecv;

Цикл продолжается, пока значение nCharRecv не станет меньше или равно нулю. Значение меньше нуля свидетельствует об ошибке (SOCKET_ERROR равен -1), а ноль означает, что соединение было закрыто. После выхода из Цикла проверяется последнее значение nCharRecv. И если случилась ошибка, выводится соответствующее сообщение:

if (nCharRecv == SOCKET_ERROR)

MessageBox(NULL, "Error occurred during recv()!", PROG_NAME,

MB_OKIMB_ICONSTOP) ;

else // Выводим информацию Finger

{

wsprintf(szFingerQuery,"%s@%s", PINGER_QUERY, HOST_NAME);

MessageBox(NULL, szFingerInfo, szFingerQuery,

MB_OKIMB__ICONINFORMATION) ;

}

Если ошибки не было, в буфере szFingerQuery формируются результаты ответа сервера, а именно туда помещается идентификатор пользователя и имя сетевого компьютера, выводимые на панель сообщения Qfinger в формате username@hostname.

Что такое протокол Finger?

Сервер Finger не нуждается в большом количестве информации. Если запрос состоит из пустой строки, он предполагает, что необходима информация обо всех работающих в данный момент в системе пользователях. Если строка-запрос не пуста, предполагается, что ее содержимое идентифицирует известного серверу пользователя, о котором запрашивается информация. В этом случае сервер выдаст всю общедоступную информацию о пользователях, имена или идентификаторы которых совпадают с содержимым запроса. Самое трудное в программе QFinger — создать и соединить сокет. Сама по себе информация Finger (и ее формат) устроена просто. Однако помимо Finger, на свете существует большое количество не столь простых протоколов. Как мы уже отмечали, иногда самый легкий способ что-либо изучить — это начать с конца и следовать к началу. Теперь, когда вы знаете, как работает программа Finger, вам будет легко понять, как устроен сам протокол.