Wsadata c что это
И так, что же такое Winsock и с чем его едят? Если сказать в "двух словах", то Winsock это интерфейс, который упрощает разработку сетевых приложений под Windows. Всё что нам нужно знать, это то что Winsock представляет собою интерфейс между приложением и транспортным протоколом, выполняющим передачу данных.
Не будем вдаваться в детали внутренней архитектуры, ведь нас интересует не то, как он устроен внутри, а то, как использовать функции, предоставляемые Winsock пользователю для работы. Наша задача — на конкретных примерах разобраться с механизмом действия WinsockAPI. "Для чего это можно использовать? Ведь существуют библиотеки, упрощающие работу с сетями и имеющие простой интерфейс?" — спросите вы. Я отчасти согласен с этим утверждением, но по-моему полностью универсальных библиотек, ориентированных под все задачи существовать не может. Да и к тому же, намного приятней разобраться во всём самому, не чувствуя неловкости перед "чёрным ящиком" принципа работы которого не понимаешь, а лишь используешь как инструмент 🙂 Весь материал рассчитан на новичков. Я думаю с его освоением не будет никаких проблем. Если вопросы всё-таки возникнут, пишите на pepper@anotherd.com. Отвечу всем. Для иллюстрации примеров будем использовать фрагменты кода Microsoft VC++. Итак, приступим!
Итак, первый вопрос — если есть Winsock, то как его использовать? На деле всё не так уж и сложно. Этап первый — подключение библиотек и заголовков.
#include "winsock.h" или #include "winsock2.h" — в зависимости от того, какую версию Winsock вы будете использовать
Так же в проект должны быть включены все соответствующие lib-файлы (Ws2_32.lib или Wsock32.lib)
Теперь мы можем спокойно использовать функции WinsockAPI. (полный список функций можно найти в соответствующих разделах MSDN).
Для инициализации Winsock вызываем функцию WSAStartup
Параметр WORD wVersionRequested — младший байт — версия, старший байт — под.версия, интерфейса Winsock. Возможные версии — 1.0, 1.1, 2.0, 2.2. Для "сборки" этого параметра используем макрос MAKEWORD. Например: MAKEWORD (1, 1) — версия 1.1. Более поздние версии отличаются наличием новых функций и механизмов расширений. Параметр lpWSAData — указатель на структуру WSADATA. При возврате из функции данная структура содержит информацию о проинициализированной нами версии WinsockAPI. В принципе, ёё можно игнорировать, но если кому-то будет интересно что же там внутри — не поленитесь, откройте документацию 😉
Так это выглядит на практике:
При ошибке функция возвращает SOCKET_ERROR. В таком случае можно получить расширенную информацию об ошибке используя вызов WSAGetLastError(). Данная функция возвращает код ошибки (тип int)
Итак, мы можем приступить к следующему этапу — создания основного средства коммуникации в Winsock- сокета (socket). С точки зрения WinsockAPI сокет — это дескриптор, который может получать или отправлять данные. На практике всё выглядит так: мы создаём сокет с определёнными свойствами и используем его для подключения, приёма/передачи данных и т.п. А теперь сделаем небольшое отступление. Итак, создавая сокет мы должны указать его параметры: сокет использует TCP/IP протокол или IPX (если TCP/IP, то какой тип и т.д.). Так как следующие разделы данной статьи будут ориентированы на TCP/IP протокол, то остановимся на особенностях сокетов использующих этот протокол. Мы можем создать два основных типа сокетов работающих по TCP/IP протоколу — SOCK_STREAM и SOCK_DGRAM (RAW socket пока оставим в покое 🙂 ). Разница в том, что для первого типа сокетов (их еще называют TCP или connection-based socket), для отправки данных сокет должен постоянно поддерживать соединение с адресатом, при этом доставка пакета адресату гарантирована. Во втором случае наличие постоянного соединения не нужно, но информацию о том, дошел ли пакет, или нет — получить невозможно (так называемые UDP или connectionless sockets). И первый и второй типы сокетов имеют своё практическое применение. Начнём наше знакомство с сокетами с TCP (connection-based) сокетов.
Для начала объявим его:
При ошибке функция возвращает INVALID_SOCKET. В таком случае можно получить расширенную информацию об ошибке используя вызов WSAGetLastError().
В предыдущем примере мы создали сокет. Что же теперь с ним делать? 🙂 Теперь мы можем использовать этот сокет для обмена данными с другими клиентами winsock-клиентами и не только. Для того, что бы установить соединение с другой машиной необходимо знать ее IP адрес и порт. Удалённая машина должна "слушать" этот порт на предмет входящих соединений (т.е. она выступает в качестве сервера). В таком случае наше приложение это клиент.
Для установки соединения используем функцию connect.
// Объявим переменную для хранения адреса
sockaddr_in s_addr;
// Заполним ее:
ZeorMemory (&s_addr, sizeof (s_addr));
// тип адреса (TCP/IP)
s_addr.sin_family = AF_INET;
//адрес сервера. Т.к. TCP/IP представляет адреса в числовом виде, то для перевода
// адреса используем функцию inet_addr.
s_addr.sin_addr.S_un.S_addr = inet_addr ("193.108.128.226");
// Порт. Используем функцию htons для перевода номера порта из обычного в //TCP/IP представление.
s_addr.sin_port = htons (1234);
// Дальше выполняем соединение:
if (SOCKET_ERROR == ( connect (s, (sockaddr *) &s_addr, sizeof (s_addr) ) ) )
<
// Error.
error = WSAGetLastError();
// .
>
При ошибке функция возвращает SOCKET_ERROR.
Теперь сокет s связан с удаленной машиной и может посылать/принимать данные только с нее.
Для того что бы послать данные используем функцию send
При ошибке функция возвращает SOCKET_ERROR.
Длинна пакета данных ограничена самим протоколом. Как узнать максимальную длину пакета данных мы рассмотрим в следующий раз. Возврат из функции не происходит до тех пор, пока данные не будут отправлены.
Принять данные от машины с которой мы предварительно установили соединение позволяет функция recv.
int actual_len = 0;
if (SOCKET_ERROR == (actual_len = recv (s, (char* ) & buff), max_packet_size, 0 ) )
<
// Error.
error = WSAGetLastError();
// .
>
Если данные получены, то функция возвращает размер полученного пакета данных (а примере — actual_len) При ошибке функция возвращает SOCKET_ERROR. Заметьте, что функции send/recv будут ждать пока не выйдет тайм-аут или не отправится/придет пакет данных. Это соответственно вызывает задержку в работе программы. Как этого избежать читайте в следующих выпусках.
Процедура закрытия активного соединения происходит с помощью функций shutdown и closesocket. Различают два типа закрытия соединений: abortive и graceful. Первый вид — это экстренное закрытие сокета (closesocket). В таком случае соединение разрывается моментально. Вызов closesocket имеет мгновенный еффект. После вызова closesocket сокет уже недоступен. Как закрыть сокет с помощью shutdown/closesocket читайте в следующих выпусках, так как эта тема требует более полного знания Winsock.
Wsadata c что это
БлогNot. Пишем консольный сервер и клиент на C++ в Windows 32/64
Пишем консольный сервер и клиент на C++ в Windows 32/64
Как обычно, создаём новый пустой проект C++, но для решения указываем имя, например, ClientServer , а для проекта — другое имя, пусть будет Server .
Потом ещё раз создаём пустой проект с именем Client , но добавляем его в то то же самое решение.
Жмём правую кнопку мыши на «исходных файлах» приложения-сервера, выбираем команды Добавить, Создать элемент, Visual C++, файл C++, имя файла с исходным текстом можно оставить Source.cpp (по умолчанию).
Вот полный исходник этого файла, откомпилированный в Visual Studio 2019 под актуальной сборкой Windows 10.
Я выбрал в стандартной панели инструментов конфигурацию Debug — X64. Если нужно, разрешить приложению работать с сетью, подтверждаем это.
Разрешить консольному приложению сервера доступ к сети
Аналогично добавляем файл Source.cpp в приложение Client , вот его полный исходный код, так как он, в сущности, очень похож, можно без столь подробных комментариев:
Обратите внимание на директивы покдлючения библиотек в начале обоих листингов.
В Обозревателе Решений жмём правую кнопку на заголовке решения (самого верхнего уровня), выбираем «Назначить запускаемые проекты», подтверждаем запуск нескольких проектов.
Запуск нескольких проектов из решения
Наши клиент и сервер могут обмениваться сообщениями в режиме чата, конечно, функционал нетрудно расширить. Работа приложения предполагает, что у вас есть нужные компоненты в системе и настройки стандартны, в частности, доступен стандартный «локалхост» с IP-адресом 127.0.0.1
Проект в работе
Так как опции решения хранятся в файле .suo вместе с асболютными путями к файлам проекта (а у вас эти пути точно не совпадут с моими), то действие со второго рисунка («Запуск нескольких проектов из решения») в скачанном проекте будет не настроено.
Русские Блоги
Здесь, чтобы объяснить эту функцию на популярном языке, она похожа на opencv, чтобы добавить функции библиотеки ссылок, cv.lib и т. Д., Чтобы добавить дополнительные зависимости, или через комментарий #pragma (lib, "cv.lib"), Затем можно включить заголовочный файл для вызова различных функций. Конечно, для программирования сокетов необходимо вызывать различные функции сокетов, но необходимы библиотека Ws2_32.lib и файл заголовка Winsock2.h. Здесь WSAStartup объясняет операционной системе, какой файл библиотеки мы хотим использовать, чтобы файл библиотеки и текущее приложение Программа связана так, что вы можете вызывать различные функции этой версии сокета.
Заголовок заголовка: Winsock2.h
Библиотека: Ws2_32.lib
Прототип: int PASCAL FAR WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData);
Параметр: wVersionRequested — это наибольший номер версии, доступный вызывающей стороне, предоставляемый API-интерфейсом Windows Sockets. Старший байт указывает младший номер версии (исправление), а младший байт указывает основной номер версии.
lpWSAData — указатель на структуру данных WSADATA, которая используется для получения сведений о реализации Windows Sockets.
Тип данных WSADATA: эта структура используется для хранения данных Windows Sockets, возвращаемых функцией WSAStartup. Содержит данные, выполненные Winsock.dll.
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
Структура WSADATA используется для сохранения информации об инициализации сокетов Windows, возвращаемой функцией WSAStartup.
Windows Sockets DLL ожидает версию спецификации Windows Sockets, используемую вызывающей стороной. Старший байт хранит младший номер версии, а младший байт хранит старший номер версии. Вы можете использовать WORD MAKEWORD (BYTE, BYTE) для возврата этого значения, например: MAKEWORD (1,1)
Самая высокая версия спецификации Windows Sockets, которую может поддерживать эта DLL. Обычно это то же самое, что и wVersion.
Для строки ASCII, заканчивающейся нулем, DLL-библиотека Windows Sockets копирует описание реализации Windows-сокетов в эту строку, включая логотип производителя. Текст (до 256 символов) может содержать любой символ, но следует отметить, что он не может содержать управляющие символы и символы форматирования. Наиболее вероятный способ его использования приложением — его отображение (может быть усечено) в информации о состоянии.
Строка ASCII, заканчивающаяся нулем. Windows Sockets DLL копирует соответствующую информацию о состоянии или конфигурации в эту строку. Windows Sockets DLL должна использовать эту информацию только в том случае, если она полезна для пользователей или сотрудников службы поддержки, ее нельзя использовать в качестве расширения поля szDescription.
Максимальное количество сокетов, которое может открыть один процесс. Реализация сокетов Windows может предоставить глобальный пул сокетов, который может быть выделен любому процессу, или он также может выделить ресурсы, принадлежащие процессу, сокету. Это число может хорошо отражать конфигурацию Windows Sockets DLL или сетевого программного обеспечения. Авторы приложений могут использовать этот номер, чтобы приблизительно указать, полезна ли реализация Windows Sockets для приложения. Например, сервер X Windows может проверить значение iMaxSockets при первом запуске: если это значение меньше 8, приложение отобразит сообщение об ошибке, указывающее пользователю перенастроить сетевое программное обеспечение (это возможность использовать текст szSystemStatus случай). Очевидно, что нет никакой гарантии, что приложение действительно может выделить сокеты iMaxSockets, потому что могут использоваться другие приложения WindowsSockets.
Максимальный размер пакета протокола пользовательских пакетов (UDP), который приложение Windows Sockets iMaxUdpDg может отправлять или получать в байтах. Если нет никаких ограничений на реализацию, тогда iMaxUdpDg равен нулю. Во многих реализациях сокетов Беркли есть неотъемлемое ограничение для пакетов UDP (при необходимости разлагается), размер составляет 8192 байта. Реализация Windows Sockets может ограничить выделение буферов повторной сборки фрагментов. Для подходящей реализации WindowsSockets минимальное значение iMaxUdpDg составляет 512. Обратите внимание, что независимо от значения iMaxUdpDg не рекомендуется отправлять широковещательный пакет, размер которого превышает максимальную единицу передачи сети (MTU). (Windows Sockets API не предоставляет механизм для обнаружения MTU, но он будет не менее 512 байт). Это было объявлено устаревшим в WinSock версии 2.0.
lpVendorInfo Указатель на структуру данных продавца. Определение этой структуры (если есть) выходит за рамки спецификации WindowsSockets. Это было объявлено устаревшим в WinSock версии 2.0.
На самом деле, проще говоря, wsastartup в основном связывает соответствующую библиотеку сокетов.
WSAStartup () — функция
1. Функция WSAStartup
int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
Программы, использующие Socket, должны вызывать функцию WSAStartup перед использованием Socket. После этого приложение может вызывать другие функции сокетов в запрошенной библиотеке сокетов.
Во-вторых, функция WSACleanup
int WSACleanup (void);
После завершения использования запрошенной библиотеки Socket приложение должно вызвать функцию WSACleanup, чтобы отсоединить библиотеку Socket и освободить системные ресурсы, занятые библиотекой Socket.
WSAStartup () — Как использовать
Когда приложение вызывает функцию WSAStartup, операционная система ищет соответствующую библиотеку Socket в соответствии с запрошенной версией Socket, а затем связывает найденную библиотеку Socket с приложением. После этого приложение может вызывать другие функции сокетов в запрошенной библиотеке сокетов. Эта функция возвращает 0 после успешного выполнения.
Пример: если программа хочет использовать версию Socket 2.1, код программы выглядит следующим образом
wVersionRequested = MAKEWORD( 2, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
Два, функция WSACleanup
int WSACleanup (void);
После завершения использования запрошенной библиотеки Socket приложение должно вызвать функцию WSACleanup, чтобы отсоединить библиотеку Socket и освободить системные ресурсы, занятые библиотекой Socket.
Интерфейс Three Socket для извлечения функций базы данных, связанных с интернет-информацией, такой как доменные имена, услуги связи и протоколы, например
[Prototype] int PASCAL FAR gethostname (char FAR * name, int namelen);
[Инструкции] Эта функция может получить имя хоста локального хоста, где:
name: указатель на буфер полученного имени хоста.
Namelen: размер буфера в байтах.
Возвращаемое значение: если ошибки нет, вернуть 0, в противном случае вернуть код ошибки.
2.gethostbyname()
struct hostent FAR * PASCAL FAR gethostbyname(const char FAR * name);
【Инструкции по применению】
Эта функция может получить соответствующий «хост» из базы данных имен хостов.
Единственное имя параметра этой функции — это имя хоста, полученное путем вызова функции gethostname (). Если ошибок нет, просто верните указатель на структуру хоста, которая может идентифицировать список «хостов».
Это соглашение позволяет Windows Sockets DLL и приложениям Windows Sockets совместно поддерживать определенный диапазон версий Windows Sockets. Если диапазоны версий перекрываются, приложение может успешно использовать DLL-файлы Windows Sockets. На следующей диаграмме WSAStartup () используется в различных приложениях. Как работает программа и версия Windows Sockets DLL:
версия приложения версия DLL wVersionRequested wVersion wHighVersion Окончательный результат
1.1 1.1 1.1 1.1 1.1 use 1.1
1.0 1.1 1.0 1.1 1.0 1.0 use 1.0
1.0 1.0 1.1 1.0 1.0 1.1 use 1.0
1.1 1.0 1.1 1.1 1.1 1.1 use 1.1
1.1 1.0 1.1 1.0 1.0 не удалось
1.0 1.1 1.0 -- -- WSAVERNOTSUPPORTED
1.0 1.1 1.0 1.1 1.1 1.1 1.1 use 1.1
1.1 2.0 1.1 2.0 1.1 1.1 use 1.1
2.0 1.1 2.0 1.1 1.1 не удалось
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) <
if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
В следующем фрагменте кода показано, как выполняется согласование WSAStartup () для DLL-библиотеки Windows Sockets, которая поддерживает только версию 1.1:
if ( LOBYTE( wVersionRequested ) < 1 || ( LOBYTE( wVersionRequested ) == 1 &&
HIBYTE( wVersionRequested ) < 1 ) )
lpWsaData->wVersion = MAKEWORD( 1, 1 );
lpWsaData->wHighVersion = MAKEWORD( 1, 1 );
После того, как приложение или DLL успешно выполнят вызов WSAStartup (), он может продолжить выполнять другие необходимые вызовы Windows Sockets API. После завершения службы с использованием Windows Sockets DLL После этого приложение или DLL должны вызывать WSACleanup (), чтобы позволить Windows Sockets DLL освобождать любые ресурсы этого приложения.
Код ошибки:
WSASYSNOTREADY указывает, что сетевая подсистема, от которой зависит сетевое взаимодействие, не готова.
Версия API Windows Sockets, требуемая WSAVERNOTSUPPORTED, не предоставляется конкретной реализацией Windows Sockets.
Версия Windows Sockets, указанная приложением WSAEINVAL, не поддерживается этой DLL.
Смотрите:
send(), sendto(), WSACleanup()。
Под Windows Socket реализован в виде DLL. Счетчик поддерживается внутри библиотеки DLL. Только первый вызов WSAStartup фактически загрузит библиотеку DLL. Последующие вызовы просто увеличивают счетчик, а функция функции WSACleanup прямо противоположна. Каждый вызов уменьшает счетчик на 1, когда счетчик уменьшается до 0. В это время DLL выгружается из памяти! Следовательно, столько раз, сколько вы вызываете WSAStartup, вы должны вызывать WSACleanup столько раз, сколько это возможно.