Сетевое программирование в .NET. Расшифровка IP-адреса (IP address specification). Обеспечение надежности доставки пакетов, страница 13

#define FD_CLR(fd, set) do { \

u_int __i; \

for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count ; __i++) { \

if (((fd_set FAR *)(set))->fd_array[__i] == fd) { \

while (__i < ((fd_set FAR *)(set))->fd_count-1) { \

((fd_set FAR *)(set))->fd_array[__i] = \

((fd_set FAR *)(set))->fd_array[__i+1]; \

__i++; \

} \

((fd_set FAR *)(set))->fd_count--; \

break; \

} \

} \

} while(0)

Я привел ее не для того, чтобы вы вникали в алгоритм манипулирования структурой fd_set (этот тип инкапсулирует массив переменных типа SOCKET), а для того, чтобы вы сравнили мир, в котором жила команда программистов, разрабатывавшая семейство API Winsock, тип их мышления, с тем, что предлагает подход к разработке ПО, основанный на платформе .NET. Полезно также вспомнить, что думает о макроподстановках Bjarne Stroustrup.

В модели Socket-программирования работают с интерфейсами сетевых устройств не прямо, а используют промежуточнные объекты (sockets). Они реализуют функциональность файловых дескрипторов и определяют:

¨  Домен коммуникации, например, сетевое соединение, или Unix IPC (Interprocess Communication) канал,

¨  Тип коммуникации (stream или datagram),

¨  Тип протокола (TCP или UDP).

Как в Unix, так и в Winsock для создания сетевого разъема используется функция:

socket (int domain, int type, int protocol);

Она возвращает целочисленный socket descriptor (типа int в Unix, или типа unsigned int в Windows), но в Windows по традиции для него введен специальный тип данных SOCKET. В Windows первый параметр функции определяет тип разъема (address family) и может принимать 2 значения:

¨  AF_INET — Internet Protocol version 4 (IPv4),

¨  AF_INET6 — Internet Protocol version 6 (IPv6).

В системе Unix этот параметр может принимать одно из 10 возможных значений (Unix IPC, Novell, Amateur radio AX.25, AppleTalk, и т. д.). Нам и далее придется сравнивать Windows-реализацию с реализацией Unix для того, чтобы понять, откуда берется излишняя сложность функций и структур данных. В системе Windows второй параметр функции socket (тип соединения) может принимать 2 значения (в Unix он допускает 5 значений):

¨  SOCK_STREAM — обеспечивает надежное соединение, или двухсторонний механизм передачи последовательного потока байтов, основанный на протоколе TCP.

¨  SOCK_DGRAM — поддерживает механизм datagram, использующий буферы фиксированного размера и основанный на протоколе UDP.

Последний параметр определяет метод (или алгоритм), применяемый для настройки (изменения параметров) протокола связи.

При работе с TCP-разъемом используется значение IPPROTO_TCP. Вообще же этот параметр может принимать множество различных значений, которые зависят от версии Windows. В системах XP/Server 2003 уровню IPPROTO_TCP соответствует настройка (Socket Option) TCP_NODELAY, которая по умолчанию включает Nagle-алгоритм управления задержкой. Он был разработан для борьбы с проблемамаи, создаваемыми пакетами малого размера (tinygrams), которые делают процесс обмена данными неэффективным. В соответствии с Nagle-алгоритмом сетевой разъем копит пакеты в буфере в течение 200 мс, а затем собирает их в один пакет и отправляет. Алгоритм учитывает также и то, что максимальный размер пакета в сети Ethernet составляет 1500 байт.

После того. как разъем (socket) создан, его надо привязать (bind) к паре (сетевой адрес, порт) либо своего, либо удаленного компьютера и только после этого разъем можно использовать для передачи данных.

Понятие address family введено в Unix для того, чтобы в качестве адреса разъема могли использоваться ссылки на различные объекты. Именно это обстоятельство объясняет такой большой размер (14 байт) поля sa_data в структуре sockaddr, которая используется для хранения IP-адреса компьютера, участвующего в обмене по правилам Winsock.

struct sockaddr

{

unsigned short sa_family;

char sa_data[14];

};