Wsadata c что это

от admin

Wsadata c что это

WSADATA, a data structure. This structure is used to store Windows Sockets data returned after the WSAStartup function is called. It contains data executed by Winsock.dll.

This structure is used to store Windows Sockets data returned after the WSAStartup function is called. It contains data executed by Winsock.dll.

wVersion
Windows Sockets DLL expects the version of the Windows Sockets specification that the caller used. High byte stores the secondary version number, the low-segment storage main version number, can return this value with Word MakeWord (Byte, Byte), for example: makeword (1, 1)
wHighVersion
This DLL can support the highest version of the Windows Sockets specification. Usually it is the same as WVersion.
szDescription
The ASCII string ends with NULL, the Windows Sockets DLL will copy the description implemented by the Windows Sockets to this string, including the manufacturer’s ID. Text (up to 256 characters) can contain any characters, but be careful not to include control characters and format characters, the application is the most likely used method to display it (possibly truncated) in status information.
szSystemStatus
ASCII string ended with NULL, the Windows Sockets DLL copies the relevant state or configuration information to the string. The Windows Sockets DLL should only use them only when this information is used for users or supporters, which should not be expanded as the Szdescription domain.
iMaxSockets
The maximum number of Sockets that a single process can open. Windows Sockets implementation can provide a global Socket pool that can be assigned to any process; or it can also assign resources that belong to the process for Socket. This number can reflect the configuration of Windows Sockets DLL or network software. The writer of the app can be roughly indicated by this number to implement whether Windows sockets implementation is useful for the application. For example, the X Windows server may check the value of iMaxSockets when the first startup: If this value is less than 8, the application will display an error message, indicating that the user reconfigures the network software (this is a possibility to use SzsystemStatus text). occasion). Obviously, an application can really assign iMaxSockets Socket because there may be other WindowsSockets applications that are being used.
iMaxUdpDg
The Windows Sockets application is capable of sending or receiving the maximum user packet protocol (UDP) packet size, in bytes. If the implementation is not limited, IMAXUDPDG is zero. In many implementations of Berkeley Sockets, there is an inherent restriction on the UDP packet (decomposed when necessary), the size is 8192 bytes. The implementation of Windows Sockets can be restricted to the allocation of the fragment restructuring buffer. For suitable WindowsSockets implementations, iMaxUDPDG minimum is 512. Note that the value of iMaxudpdg is not recommended, you don’t recommend that you send back a broadcast data package that is larger than the maximum transfer unit (MTU). (Windows Sockets API does not provide a mechanism for discovering MTU, but it will not be less than 512 bytes). WinSock 2.0 has been discarded.
lpVendorInfo
Pointer to the distributor’s data structure. The definition of this structure (if any) exceeds the range of WindowsSockets specifications. WinSock 2.0 has been discarded.

In the MFC, the WSADATA structure is the function returned by AFXSocketinit and calls your InitInstance function. If you need to use information from it, you can retrieve the structure and store it in your program.
WSAStartup assigns some column values ​​to members of the WSADATA structure:
WVERSION WVERSIONREQUESTED value
WHIGHVERSION WVERSIONREQUESTED value
SZDescription Null string
SzsystemStatus null string
iMaxSockets 100
iMaxUdpDg 0
lpVendorInfo NULL
Prerequisites:
operating system
Windows CE
Version:
More than equal to 1.0
Define location:
Winsock.h
Note:
This API is part of the complete Windows CE operating system package provided by Microsoft. This feature depends on the original device manufacturer, and some devices may not support this API.

Wsadata c что это

Socket (гнездо, разъем) — абстрактное программное понятие, используемое для обозначения в прикладной программе конечной точки канала связи с коммуникационной средой, образованной вычислительной сетью. При использовании протоколов TCP/IP можно говорить, что socket является средством подключения прикладной программы к порту локального узла сети.

Socket-интерфейс представляет собой просто набор системных вызовов и/или библиотечных функций языка программирования СИ, разделенных на четыре группы:

Ниже рассматривается подмножество функций socket-интерфейса, достаточное для написания сетевых приложений, реализующих модель "клиент-сервер" в режиме с установлением соединения. Все функции сокетов содержаться в wsock32.dll перед тем как написать программу с использование функций сокетов необходимо задать компилятору чтобы он включил в программу файл wsock32.lib. В меню Рroject выберите пункт settings а там укажите раздел Link, wsock32.lib можно ввести в поле Library modules или project options. Не забудьте поставить #include "Winsock2.h".

1. Создание сервера

Прежде чем воспользоваться функцией socket необходимо проинициализировать процесс библиотеки wsock32.dll вызвав функцию WSAStartup например: Здесь 0х0101 версия библиотеки которую следует использовать.

    s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

Создание socket’а осуществляется следующим системным вызовом

Аргумент domain задает используемый для взаимодействия набор протоколов (вид коммуникационной области), для стека протоколов TCP/IP он должен иметь символьное значение AF_INET.

Аргумент type задает режим взаимодействия:

  • SOCK_STREAM — с установлением соединения;
  • SOCK_DGRAM — без установления соединения.

Аргумент protocol задает конкретный протокол транспортного уровня (из нескольких возможных в стеке протоколов). Если этот аргумент задан равным 0, то будет использован протокол "по умолчанию" (TCP для SOCK_STREAM и UDP для SOCK_DGRAM при использовании комплекта протоколов TCP/IP).

При удачном завершении своей работы данная функция возвращает дескриптор socket’а — целое неотрицательное число, однозначно его идентифицирующее. Дескриптор socket’а аналогичен дескриптору файла ОС UNIX.

При обнаружении ошибки в ходе своей работы функция возвращает число "-1".

Далее мы задаем параметры для сокета (сервера) для этого нам необходимо объявить структуру SOCKADDR_IN sin далее заполняем параметры для сервера:

Структура SOCKADDR_IN используется несколькими системными вызовами и функциями socket-интерфейса и определена в include-файле in.h следующим образом:

Поле sin_family определяет используемый формат адреса (набор протоколов), в нашем случае (для TCP/IP) оно должно иметь значение AF_INET.

Поле sin_addr содержит адрес (номер) узла сети.

Поле sin_port содержит номер порта на узле сети.

Поле sin_zero не используется.

Определение структуры in_addr (из того же include-файла) таково:

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

Для подключения socket’а к коммуникационной среде, образованной вычислительной сетью, необходимо выполнить системный вызов bind , определяющий в принятом для сети формате локальный адрес канала связи со средой. В сетях TCP/IP socket связывается с локальным портом. Системный вызов bind имеет следующий синтаксис:

    err = bind( s, (LPSOCKADDR)&sin, sizeof(sin) );

Аргумент s задает дескриптор связываемого socket’а.

Аргумент addr в общем случае должен указывать на структуру данных, содержащую локальный адрес, приписываемый socket’у. Для сетей TCP/IP такой структурой является SOCKADDR_IN.

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

В случае успеха bind возвращает 0, в противном случае — "-1".

Для установления связи "клиент-сервер" используются системные вызовы listen и accept (на стороне сервера), а также connect (на стороне клиента). Для заполнения полей структуры socaddr_in, используемой в вызове connect , обычно используется библиотечная функция gethostbyname, транслирующая символическое имя узла сети в его номер (адрес).

Системный вызов listen выражает желание выдавшей его программы-сервера ожидать запросы к ней от программ-клиентов и имеет следующий вид:

    err = listen( s, SOMAXCONN);

Аргумент s задает дескриптор socket’а, через который программа будет ожидать запросы к ней от клиентов. Socket должен быть предварительно создан системным вызовом socket и обеспечен адресом с помощью системного вызова bind .

Аргумент n определяет максимальную длину очереди входящих запросов на установление связи. Если какой-либо клиент выдаст запрос на установление связи при полной очереди, то этот запрос будет отвергнут.

Признаком удачного завершения системного вызова listen служит нулевой код возврата.

    printf(«accepted connection from %s, port %d\n», inet_ntoa(from.sin_addr), htons(from.sin_port)) ;

Для приема запросов от программ-клиентов на установление связи в программах-серверах используется системный вызов accept , имеющий следующий вид:

Аргумент s задает дескриптор socket’а, через который программа-сервер получила запрос на соединение (посредством системного запроса listen ).

Аргумент addr должен указывать на область памяти, размер которой позволял бы разместить в ней структуру данных, содержащую адрес socket’а программы-клиента, сделавшей запрос на соединение. Никакой инициализации этой области не требуется.

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

Системный вызов accept извлекает из очереди, организованной системным вызовом listen , первый запрос на соединение и возвращает дескриптор нового (автоматически созданного) socket’а с теми же свойствами, что и socket, задаваемый аргументом s. Этот новый дескриптор необходимо использовать во всех последующих операциях обмена данными.

Кроме того после удачного завершения accept :

  1. область памяти, указываемая аргументом addr, будет содержать структуру данных (для сетей TCP/IP это sockaddr_in), описывающую адрес socket’а программы-клиента, через который она сделала свой запрос на соединение;
  2. целое число, на которое указывает аргумент p_addrlen, будет равно размеру этой структуры данных.

Если очередь запросов на момент выполнения accept пуста, то программа переходит в состояние ожидания поступления запросов от клиентов на неопределенное время (хотя такое поведение accept можно и изменить).

Признаком неудачного завершения accept служит отрицательное возвращенное значение (дескриптор socket’а отрицательным быть не может).

Примечание. Системный вызов accept используется в программах-серверах, функционирующих только в режиме с установлением соединения.

Вот мы соединились с клиентом, но как получить и передать информацию? Это делается с помощью команд send и recv ко не забывайте что вы теперь работаете с переменной s1: Мы поставили цикл while, потому что он будет выполнятся пока клиент не отключится

Для получения данных от партнера по сетевому взаимодействию используется системный вызов recv , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который принимаются данные.

Аргумент buf указывает на область памяти, предназначенную для размещения принимаемых данных.

Аргумент len задает длину (в байтах) этой области.

Аргумент flags модифицирует исполнение системного вызова recv . При нулевом значении этого аргумента вызов recv полностью аналогичен системному вызову read .

При успешном завершении recv возвращает количество принятых в область, указанную аргументом buf , байт данных. Если канал данных, определяемый дескриптором s, оказывается "пустым", то recv переводит программу в состояние ожидания до момента появления в нем данных.

Для посылки данных партнеру по сетевому взаимодействию используется системный вызов send , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который посылаются данные.

Аргумент buf указывает на область памяти, содержащую передаваемые данные.

Аргумент len задает длину (в байтах) передаваемых данных.

Аргумент flags модифицирует исполнение системного вызова send . При нулевом значении этого аргумента вызов send полностью аналогичен системному вызову write .

При успешном завершении send возвращает количество переданных из области, указанной аргументом buf, байт данных. Если канал данных, определяемый дескриптором s, оказывается "переполненным", то send переводит программу в состояние ожидания до момента его освобождения.

Для закрытия ранее созданного socket’а используется обычный системный вызов closesocket , применяемый в ОС UNIX для закрытия ранее открытых файлов и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Однако в режиме с установлением логического соединения (обеспечивающем, как правило, надежную доставку данных) внутрисистемные механизмы обмена будут пытаться передать/принять данные, оставшиеся в канале передачи на момент закрытия socket’а. На это может потребоваться значительный интервал времени, неприемлемый для некоторых приложений. В такой ситуации необходимо использовать описываемый далее системный вызов shutdown .

2. Создание клиента

    connect(s, (struct sockaddr *)&anAddr, sizeof(struct sockaddr));

Для обращения программы-клиента к серверу с запросом на установление логической соединения используется системный вызов connect , имеющий следующий вид

Аргумент s задает дескриптор socket’а, через который программа обращается к серверу с запросом на соединение. Socket должен быть предварительно создан системным вызовом socket и обеспечен адресом с помощью системного вызова bind .

Аргумент addr должен указывать на структуру данных, содержащую адрес, приписанный socket’у программы-сервера, к которой делается запрос на соединение. Для сетей TCP/IP такой структурой является sockaddr_in. Для формирования значений полей структуры sockaddr_in удобно использовать функцию gethostbyname .

Аргумент addrlen задает размер (в байтах) структуры данных, указываемой аргументом addr.

Для того, чтобы запрос на соединение был успешным, необходимо, по крайней мере, чтобы программа-сервер выполнила к этому моменту системный вызов listen для socket’а с указанным адресом.

При успешном выполнении запроса системный вызов connect возвращает 0, в противном случае — "-1" (устанавливая код причины неуспеха в глобальной переменной errno).

Примечание. Если к моменту выполнения connect используемый им socket не был привязан к адресу посредством bind , то такая привязка будет выполнена автоматически.

Примечание. В режиме взаимодействия без установления соединения необходимости в выполнении системного вызова connect нет. Однако, его выполнение в таком режиме не является ошибкой — просто меняется смысл выполняемых при этом действий: устанавливается адрес "по умолчанию" для всех последующих посылок дейтаграмм.

Вот наконец установлена долгожданная связь c сервером( не забывайте проверять ошибки). Дальше воспользуемся функциями send и recv по своему усмотрению.

3. Приложение

Для получения адреса узла сети TCP/IP по его символическому имени используется библиотечная функция

Аргумент name задает адрес последовательности литер, образующих символическое имя узла сети.

При успешном завершении функция возвращает указатель на структуру hostent, определенную в include-файле netdb.h и имеющую следующий вид

Поле h_name указывает на официальное (основное) имя узла.

Поле h_aliases указывает на список дополнительных имен узла (синонимов), если они есть.

Поле h_addrtype содержит идентификатор используемого набора протоколов, для сетей TCP/IP это поле будет иметь значение AF_INET.

Поле h_lenght содержит длину адреса узла.

Поле h_addr указывает на область памяти, содержащую адрес узла в том виде, в котором его используют системные вызовы и функции socket-интерфейса.

Для "экстренного" закрытия связи с партнером (путем "сброса" еще не переданных данных) используется системный вызов shutdown , выполняемый перед close и имеющий следующий вид

Аргумент s задает дескриптор ранее созданного socket’а.

Аргумент how задает действия, выполняемые при очистке системных буферов socket’а:

Purely functional

Клиентские сокеты используют приложения, которым необходимо передавать и принимать данные с другим приложением. Примером такого приложения является браузер: по определенному ip-адресу он передает серверу сформированный HTTP-заголовок, в качестве ответа сервер передает данные, которые затребовал в HTTP-заголовке клиент (web-страницу, изображение и т.п.).
В этой статье я расскажу о средствах WSA, необходимых для реализации передачи данных между процессами через клиентские сокеты.

Инициализация WSA

Перед началом работы с сокетами Windows необходимо инициализировать Windows sockets API (WSA)
Для этого надо вызывать функцию WSAStartup и передать в аргументах версию WSA и указатель на структуру WSAData. Функция возвращает 0, если инициализация прошла успешно, в противном случае возвращает код ошибки.

Создание сокета

Функция socket возвращает дескриптор сокета. Если при создании сокета произошла ошибка, она возвращает 0 (INVALID_SOCKET).

Присоединение к серверу

После того как сокет создан, можно начинать подключаться через него к серверам.
Для соединения нужен сам сокет, ip-адрес и порт процесса (сервера). Эти данные передаются функции connect, которая возвращает 0 в случае успешного соединения.
Ip-адрес и порт следует передать структуре sockaddr.

Передача данных серверу

Для передачи данных серверу необходимо вызвать функцию send. Вторым аргументом является указатель на данные, третьим количество данных.
Функция возвращает отрицательное число, если произошла ошибка, иначе возвращается число, соответствующие количеству переданных данных.

Прием данных от сервера

Что бы принять данные надо вызывать функцию recv и передать ей в качестве аргументов указатель на буфер данных и на размер этого буфера.
Из кода видно, что за один раз можно принять не более bufsize байт информации.

Разрыв соединения

Заключение

Дополнительную информацию о функциях, структурах WSA можно найти в MSDN: Winsock reference.

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.

Читать:
Как включить дабл клик на мышке

Похожие статьи