Инициализируйте nNameLen значением sizeof (struct sockaddr_in).
Возвращаемое значение 0 указывает на успешное завершение функции, тогда как значение SOCKET_ERROR указывает на ошибку, которая, в частности, может быть обусловлена отсутствием прослушивающего сокета по указанному адресу.
Сокет s не обязательно должен быть связанным с портом до вызова функции connect, хотя это и может иметь место. При необходимости система распределяет порт и определяет протокол.
Пример: подключение клиента к серверу
Показанный ниже фрагмент кода обеспечивает соединение клиента с сервером. Для этого нужны только два вызова функций, но адресная структура должна быть инициализирована до вызова функции connect. Проверка возможных ошибок здесь отсутствует, но в реальные программы она должна включаться. В примере предполагается, что IP-адрес (текстовая строка наподобие "192.76.33.4") задается в аргументе argv[1] командной строки.
SOCKET ClientSock;
…
ClientSock = socket(AF_INET, SOCK_STREAM, 0);
memset(&ClientSAddr, 0, sizeof(ClientSAddr));
ClientSAddr.sin_family = AF_INET;
ClientSAddr.sin_addr.s_addr = inet_addr(argv[1]);
ClientSAddr.sin_port = htons(SERVER_PORT);
ConVal = connect(ClientSock, (struct sockaddr *)&ClientSAddr, sizeof(ClientSAddr));
Отправка и получение данных
Программы, использующие сокеты, обмениваются данными с помощью функций send и recv, прототипы которых почти совпадают (перед указателем буфера функции send помещается модификатор const). Ниже представлен только прототип функции send.
int send(SOCKET s, const char * lpBuffer, int nBufferLen, int nFlags);
Возвращаемым значением является число фактически переданных байтов. Значение SOCKET_ERROR указывает на ошибку.
nFlags — может использоваться для обозначения степени срочности сообщений (например, экстренных сообщений), а значение MSG_PEEK позволяет просматривать получаемые данные без их считывания.
Самое главное, что вы должны запомнить — это то, что функции send и recv
С сокетами могут использоваться также функции ReadFile и WriteFile, только в этом случае при вызове функции необходимо привести сокет к типу HANDLE.
Сравнение именованных каналов и сокетов
Именованные каналы, описанные в главе 11, очень похожи на сокеты, но в способах их использования имеются значительные различия.
• Именованные каналы могут быть ориентированными на работу с сообщениями, что значительно упрощает программы.
• Именованные каналы требуют использования функций ReadFile и WriteFile, в то время как сокеты могут обращаться также к функциям send и recv.
• В отличие от именованных каналов сокеты настолько гибки, что предоставляют пользователям возможность выбрать протокол для использования с сокетом, например, TCP или UDP. Кроме того, пользователь имеет возможность выбирать протокол на основании характера предоставляемой услуги или иных факторов.
• Сокеты основаны на промышленном стандарте, что обеспечивает их совместимость с системами, отличными от Windows.
Имеются также различия в моделях программирования сервера и клиента.
Сравнение серверов именованных каналов и сокетов
Установка соединения с несколькими клиентами при использовании сокетов требует выполнения повторных вызовов функции accept. Каждый из вызовов возвращает очередной подключенный сокет. По сравнению с именованными каналами имеются следующие отличия:
• В случае именованных каналов требуется, чтобы каждый экземпляр именованного канала и дескриптор типа HANDLE создавались с помощью функции CreateNamedPipe, тогда как для создания экземпляров сокетов применяется функция accept.
• Допустимое количество клиентских сокетов ничем не ограничено (функция listen ограничивает лишь количество клиентов, помещаемых в очередь), в то время как количество экземпляров именованных каналов, в зависимости от того, что было указано при первом вызове функции CreateNamedPipe, может быть ограниченным.
• Не существует вспомогательных функций для работы с сокетами, аналогичных функции TransactNamedPipe.