Что такое сокеты windows

Начинающему сетевому программисту

Время на прочтение17 мин

Количество просмотров144K

Тема сетевого программирования является для разработчиков одной из важнейших в современном цифровом мире. Правда, надо признать, что большая часть сетевого программирования сосредоточена в области написания скриптов исполнения для web-серверов на языках PHP, Python и им подобных. Как следствие — по тематике взаимодействия клиент-сервер при работе с web-серверами написаны терабайты текстов в Интернете. Однако когда я решил посмотреть, что же имеется в Интернете по вопросу программирования сетевых приложений с использованием голых сокетов, то обнаружил интересную вещь: да, такие примеры конечно же есть, но подавляющее большинство написано под *nix-системы с использованием стандартных библиотек (что понятно – в области сетевого программирования Microsoft играет роль сильно отстающего и менее надежного «собрата» *nix-ов). Другими словами все эти примеры просто не будут работать под Windows. При определенных танцах с бубнами код сетевого приложения под Linux можно запустить и под Windows, однако это еще более запутает начинающего программиста, на которого и нацелены большинство статей в Интернете с примерами использования сокетов.

Ну а что же с документацией по работе с сетевыми сокетами в Windows от самой Microsoft? Парадоксальность ситуации заключается в том, что непосредственно в самой документации приведено очень беглое описание функций и их использования, а в примерах имеются ошибки и вызовы старых «запрещенных» современными компиляторами функций (к примеру, функция inet_addr() — https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen ) — такие функции конечно же можно вызывать, заглушив бдительность компилятора через #define-директивы, однако такой подход является полным зашкваром для любого даже начинающего программиста и категорически не рекомендуется к использованию. Более того, фрагмент кода в примере от Microsoft по ссылке выше:

service.sin_addr.s_addr = inet_addr("127.0.0.1");

вообще не заработает, т.к. полю Service.sin_addr.s_addr невозможно присвоить значение целого типа, которое возвращает функция inet_addr (возвращает unsigned long). То есть это ни много, ни мало — ошибка! Можно себе представить, сколько пытливых бойцов полегло на этом месте кода.

В общем, посмотрев на всё это, я решил написать базовую статью по созданию простейшего клиент-сервер приложения на С++ под Windows с детальным описанием всех используемых функций. Это приложение будет использовать Win32API и делать незамысловатую вещь, а именно: передавать сообщения от клиента к серверу и обратно, или, иначе говоря – напишем программу по реализации чата для двух пользователей.

Сразу оговорюсь, что статья рассчитана на начинающих программистов, которые только входят в сетевое программирование под Windows. Необходимые навыки – базовое знание С++, а также теоретическая подготовка по теме сетевых сокетов и стека технологии TCP/IP.

Теория сокетов за 30 секунд для «dummies»

Начну всё-таки немного с теории в стиле «for dummies». В любой современной операционной системе, все процессы инкапсулируются, т.е. скрываются друг от друга, и не имеют доступа к ресурсам друг друга. Однако существуют специальные разрешенные способы взаимодействия процессов между собой. Все эти способы взаимодействия процессов можно разделить на 3 группы: (1) сигнальные, (2) канальные и (3) разделяемая память.

Когда мы говорим про работу сетевого приложения, то всегда подразумеваем взаимодействие процессов: процесс 1 (клиент) пытается что-то послать или получить от Процесса 2 (сервер). Наиболее простым и понятным способом организации сетевого взаимодействия процессов является построение канала между этими процессами. Именно таким путём и пошли разработчики первых сетевых протоколов. Получившийся способ взаимодействия сетевых процессов в итоге оказался многоуровневым: основной программный уровень — стек сетевой технологии TCP/IP, который позволяет организовать эффективную доставку пакетов информации между различными машинами в сети, а уже на прикладном уровне тот самый «сокет» позволяет разобраться какой пакет какому процессу доставить на конкретной машине.

Иными словами «сокет» — это «розетка» конкретного процесса, в которую надо подключиться, чтобы этому процессу передать какую-либо информацию. Договорились, что эта «розетка» в Сети описывается двумя параметрами – IP-адресом (для нахождения машины в сети) и Портом подключения (для нахождения процесса-адресата на конкретной машине).

Для того, чтобы сокеты заработали под Windows, необходимо при написании программы пройти следующие Этапы:

  1. Инициализация сокетных интерфейсов Win32API.

  2. Инициализация сокета, т.е. создание специальной структуры данных и её инициализация вызовом функции.

  3. «Привязка» созданного сокета к конкретной паре IP-адрес/Порт – с этого момента данный сокет (его имя) будет ассоциироваться с конкретным процессом, который «висит» по указанному адресу и порту.

  4. Для серверной части приложения: запуск процедуры «прослушки» подключений на привязанный сокет.

    Для клиентской части приложения: запуск процедуры подключения к серверному сокету (должны знать его IP-адрес/Порт).

  5. Акцепт / Подтверждение подключения (обычно на стороне сервера).

  6. Обмен данными между процессами через установленное сокетное соединение.

  7. Закрытие сокетного соединения.

     Итак, попытаемся реализовать последовательность Этапов, указанных выше, для организации простейшего чата между клиентом и сервером. Запускаем Visual Studio, выбираем создание консольного проекта на С++ и поехали.

Этап 0: Подключение всех необходимых библиотек Win32API для работы с сокетами

Сокеты не являются «стандартными» инструментами разработки, поэтому для их активизации необходимо подключить ряд библиотек через заголовочные файлы, а именно:

  • WinSock2.h – заголовочный файл, содержащий актуальные реализации функций для работы с сокетами.

  • WS2tcpip.h – заголовочный файл, который содержит различные программные интерфейсы, связанные с работой протокола TCP/IP (переводы различных данных в формат, понимаемый протоколом и т.д.).

  • Также нам потребуется прилинковать к приложению динамическую библиотеку ядра ОС: ws2_32.dll. Делаем это через директиву компилятору: #pragma comment(lib, “ws2_32.lib”)

  • Ну и в конце Этапа 0 подключаем стандартные заголовочные файлы iostream и stdio.h   

Итого по завершению Этапа 0 в Серверной и Клиентской частях приложения имеем:

#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#include <vector>

#pragma comment(lib, "Ws2_32.lib")

Обратите внимание: имя системной библиотеки ws2_32.libименно такое, как это указано выше. В Сети есть различные варианты написания имени данной библиотеки, что, возможно, связано иным написанием в более ранних версиях ОС Windows. Если вы используете Windows 10, то данная библиотека называется именно ws2_32.libи находится в стандартной папке ОС: C:/Windows/System32 (проверьте наличие библиотеки у себя, заменив расширение с “lib” на “dll”).

Этап 1: Инициализация сокетных интерфейсов Win32API

Прежде чем непосредственно создать объект сокет, необходимо «запустить» программные интерфейсы для работы с ними. Под Windows это делается в два шага следующим образом:

  • Нужно определить с какой версией сокетов мы работаем (какую версию понимает наша ОС) и

  • Запустить программный интерфейс сокетов в Win32API. Ну либо расстроить пользователя тем, что ему не удастся поработать с сокетами до обновления системных библиотек

Первый шаг делается с помощью создания структуры типа WSADATA, в которую автоматически в момент создания загружаются данные о версии сокетов, используемых ОС, а также иная связанная системная информация:WSADATA wsData;

Второй шаг – непосредственный вызов функции запуска сокетов с помощью WSAStartup(). Упрощённый прототип данной функции выглядит так:

int WSAStartup (WORD <запрашиваемая версия сокетов>, WSADATA* <указатель на структуру, хранящую текущую версию реализации сокетов>)

Первый аргумент функции – указание диапазона версий реализации сокетов, которые мы хотим использовать и которые должны быть типа WORD. Этот тип данных является внутренним типом Win32API и представляет собой двухбайтовое слово (аналог в С++: unsigned short). Функция WSAStartup() просит вас передать ей именно WORD, а она уже разложит значение переменной внутри по следующему алгоритму: функция считает, что в старшем байте слова указана минимальная версия реализации сокетов, которую хочет использовать пользователь, а в младшем – максимальная. По состоянию на дату написания этой статьи (октябрь 2021 г.) актуальная версия реализации сокетов в Windows – 2. Соответственно, желательно передать и в старшем, и в младшем байте число 2. Для того, чтобы создать такую переменную типа WORD и передать в её старший и младший байты число 2, можно воспользоваться Win32API функцией MAKEWORD(2,2).

Можно немного повыёживаться и вспомнить (или полистать MSDN), что функция MAKEWORD(x,y) строит слово по правилу y << 8 | x.Нетрудно посчитать, что при x=y=2 значение функции MAKEWORD в десятичном виде будет 514. Можешь смело передать в WSAStartup() это значение, и всё будет работать.

Второй аргумент функции – просто указатель на структуру WSADATA, которую мы создали ранее и в которую подгрузилась информация о текущей версии реализации сокетов на данной машине.

WSAStartup() в случае успеха возвращает 0, а в случае каких-то проблем возвращает код ошибки, который можно расшифровать последующим вызовом функции WSAGetLastError().

Важное замечание: поскольку сетевые каналы связи и протоколы в теории считаются ненадежными (это отдельный большой разговор), то критически важно для сетевого приложения анализировать все возможные ошибки, которые возникают в процессе вызовов сокетных функций. По этой причине каждый вызов таких функций мы будем анализировать на ошибки и в случае их обнаружения завершать сетевые сеансы и закрывать открытые сокеты. Используем для этого переменную erStat типа int.

Также важно после работы приложения обязательно закрыть использовавшиеся сокеты с помощью функции closesocket(SOCKET <имя сокета>) и деинициализировать сокеты Win32API через вызов метода WSACleanup().

Итого код Этапа 1 следующий:

WSADATA wsData;
		
int erStat = WSAStartup(MAKEWORD(2,2), &wsData);
	
	if ( erStat != 0 ) {
		cout << "Error WinSock version initializaion #";
		cout << WSAGetLastError();
		return 1;
	}
	else
		cout << "WinSock initialization is OK" << endl;

Да, кода мало, а описания много. Так обычно и бывает, когда хочешь глубоко в чем-то разобраться. Так что на лабе будешь в первых рядах.

Этап 2: Создание сокета и его инициализация

Сокет в С++ – это структура данных (не класс) типа SOCKET. Её инициализация проводится через вызов функции socket(), которая привязывает созданный сокет к заданной параметрами транспортной инфраструктуре сети. Выглядит прототип данной функции следующим образом:

SOCKET socket(int <семейство используемых адресов>, int <тип сокета>, int <тип протокола>)

  • Семейство адресов: сокеты могут работать с большим семейством адресов. Наиболее частое семейство – IPv4. Указывается как AF_INET.

  • Тип сокета: обычно задается тип транспортного протокола TCP (SOCK_STREAM) или UDP (SOCK_DGRAM). Но бывают и так называемые «сырые» сокеты, функционал которых сам программист определяет в процессе использования. Тип обозначается SOCK_RAW

  • Тип протокола: необязательный параметр, если тип сокета указан как TCP или UDP – можно передать значение 0. Тут более детально останавливаться не будем, т.к. в 95% случаев используются типы сокетов TCP/UDP.

При необходимости подробно почитать про функцию socket() можно здесь.

Функция socket() возвращает дескриптор с номером сокета, под которым он зарегистрирован в ОС. Если же инициализировать сокет по каким-то причинам не удалось – возвращается значение INVALID_SOCKET.

Код Этапа 2 будет выглядеть так:

SOCKET ServSock = socket(AF_INET, SOCK_STREAM, 0);

	if (ServSock == INVALID_SOCKET) {
		cout << "Error initialization socket # " << WSAGetLastError() << endl; 
		closesocket(ServSock);
		WSACleanup();
		return 1;
	}
	else
		cout << "Server socket initialization is OK" << endl;

Этап 3: Привязка сокета к паре IP-адрес/Порт

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

Такое назначение делается с помощью функции bind(), имеющей следующий прототип:

int bind(SOCKET <имя сокета, к которому необходимо привязать адрес и порт>, sockaddr* <указатель на структуру, содержащую детальную информацию по адресу и порту, к которому надо привязать сокет>, int <размер структуры, содержащей адрес и порт>)

Функция bind() возвращает 0, если удалось успешно привязать сокет к адресу и порту, и код ошибки в ином случае, который можно расшифровать вызовом WSAGetLastError() — см. итоговый код Этапа 3 далее.

Тут надо немножно притормозить и разобраться в том, что за такая структура типа sockaddr передается вторым аргументом в функцию bind(). Она очень важна, но достаточно запутанная.

Итак, если посмотреть в её внутренности, то выглядят они очень просто: в ней всего два поля – (1) первое поле хранит семейство адресов, с которыми мы уже встречались выше при инициализации сокета, а (2) второе поле хранит некие упакованные последовательно и упорядоченные данные в размере 14-ти байт. Бессмысленно разбираться детально как именно эти данные упакованы, достаточно лишь понимать, что в этих 14-ти байтах указан и адрес, и порт, а также дополнительная служебная информация для других системных функций Win32API.

Но как же явно указать адрес и порт для привязки сокета? Для этого нужно воспользоваться другой структурой, родственной sockaddr, которая легко приводится к этому типу — структурой типа sockaddr_in.

В ней уже более понятные пользователю поля, а именно:

  • Семейство адресов — опять оно (sin_family)

  • Порт (sin_port)

  • Вложенная структура типа in_addr, в которой будет храниться сам сетевой адрес (sin_addr)

  • Технический массив на 8 байт (sin_zero[8])

При приведении типа sockaddr_in к нужному нам типу sockaddr для использования в функции bind() поля Порт (2 байта), Сетевой адрес (4 байта) и Технический массив (8 байт) как раз в сумме дают нам 14 байт, помещающихся в 14 байт, находящихся во втором поле структуры sockaddr. Первые поля у указанных типов совпадают – это семейство адресов сокетов (указываем AF_INET). Из этого видно, что структуры данных типа sockaddr и sockaddr_in тождественны, содержат одну и ту же информацию, но в разной форме для разных целей.

Соответственно, ввод данных для структуры типа sockaddr_in выглядит следующим образом:

  1. Создание структуры типа sockaddr_in : sockaddr_in servInfo;

  2. Заполнение полей созданной структуры servInfo

  • servInfo.sin_family = AF_INET;

  • servInfo.sin_port = htons(<указать номер порта как unsigned short>); порт всегда указывается через вызов функции htons(), которая переупаковывает привычное цифровое значение порта типа unsigned short в побайтовый порядок понятный для протокола TCP/IP (протоколом установлен порядок указания портов от старшего к младшему байту или «big-endian»).

  • Далее нам надо указать сетевой адрес для сокета. Тип этого поля – структура типа in_addr, которая по своей сути представляет просто особый «удобный» системным функциям вид обычного строчного IPv4 адреса. Таким образом, чтобы указать этому полю обычный IPv4 адрес, его нужно сначала преобразовать в особый числовой вид и поместить в структуру типа in_addr .

    Благо существует функция, которая переводит обычную строку типа char[], содержащую IPv4 адрес в привычном виде с точками-разделителями в структуру типа in_addr – функция inet_pton(). Прототип функции следующий:

    int inet_pton(int <семейство адресов>, char[] <строка, содержащая IP-адрес в обычном виде с точкой-разделителем>, in_addr* <указатель на структуру типа in_addr, в которую нужно поместить результат приведения строчного адреса в численный>).

    В случае ошибки функция возвращает значение меньше 0.

    Соответственно, если мы хотим привязать сокет к локальному серверу, то наш код по преобразованию IPv4 адреса будет выглядеть так:

    in_addr ip_to_num;

    erStat = inet_pton(AF_INET, “127.0.0.1”, &ip_to_num);

    if (erStat <= 0) {

                 cout << "Error in IP translation to special numeric format" << endl;

                 return 1;

           }

    Результат перевода IP-адреса содержится в структуре ip_to_num. И далее мы передаем уже в нашу переменную типа sockaddr_in значение преобразованного адреса:

    servInfo.sin_addr = ip_to_num;

Вся нужная информация для привязки сокета теперь у нас есть, и она хранится в структуре servInfo. Можно смело вызывать функцию bind(), не забыв при этом привести servInfo из типа sockaddr_in в требуемый функцииsockaddr*. Тогда итоговый код Этапа 3 (слава богу закончили) выглядит так:

in_addr ip_to_num;
erStat = inet_pton(AF_INET, “127.0.0.1”, &ip_to_num);
if (erStat <= 0) {
		cout << "Error in IP translation to special numeric format" << endl;
		return 1;
	}

sockaddr_in servInfo;
ZeroMemory(&servInfo, sizeof(servInfo));	
				
servInfo.sin_family = AF_INET;
servInfo.sin_addr = ip_to_num;	
servInfo.sin_port = htons(1234);

erStat = bind(ServSock, (sockaddr*)&servInfo, sizeof(servInfo));
if ( erStat != 0 ) {
		cout << "Error Socket binding to server info. Error # " << WSAGetLastError() << endl;
		closesocket(ServSock);
		WSACleanup();
		return 1;
	}
	else 
		cout << "Binding socket to Server info is OK" << endl;

Этап 4 (для сервера): «Прослушивание» привязанного порта для идентификации подключений

Серверная часть готова к прослушке подключающихся «Клиентов». Для того, чтобы реализовать данный этап, нужно вызвать функцию listen(), прототип которой:

int listen(SOCKET <«слушающий» сокет, который мы создавали на предыдущих этапах>, int <максимальное количество процессов, разрешенных к подключению>)

Второй аргумент: максимально возможное число подключений устанавливается через передачу параметр SOMAXCONN(рекомендуется). Если нужно установить ограничения на количество подключений – нужно указать SOMAXCONN_HINT(N), где N – кол-во подключений. Если будет подключаться больше пользователей, то они будут сброшены.

После вызова данной функции исполнение программы приостанавливается до тех пор, пока не будет соединения с Клиентом, либо пока не будет возвращена ошибка прослушивания порта. Код Этапа 4 для Сервера:

erStat = listen(ServSock, SOMAXCONN);

	if ( erStat != 0 ) {
		cout << "Can't start to listen to. Error # " << WSAGetLastError() << endl;
		closesocket(ServSock);
		WSACleanup();
		return 1;
	}
	else {
		cout << "Listening..." << endl;
	}

Этап 4 (для Клиента). Организация подключения к серверу

Код для Клиента до текущего этапа выглядит даже проще: необходимо исполнение Этапов 0, 1 и 2. Привязка сокета к конкретному процессу (bind()) не требуется, т.к. сокет будет привязан к серверному Адресу и Порту через вызов функции connect()(по сути аналог bind() для Клиента). Собственно, после создания и инициализации сокета на клиентской стороне, нужно вызвать указанную функциюconnect(). Её прототип:

int connect(SOCKET <инициализированный сокет>, sockaddr* <указатель на структуру, содержащую IP-адрес и Порт сервера>, int <размер структуры sockaddr>)

Функция возвращает 0 в случае успешного подключения и код ошибки в ином случае.

Процедура по добавлению данных в структуру sockaddr аналогична тому, как это делалось на Этапе 3 для Сервера при вызове функции bind(). Принципиально важный момент – в эту структуру для клиента должна заноситься информация о сервере, т.е. IPv4-адрес сервера и номер «слушающего» порта на сервере.

sockaddr_in servInfo;

ZeroMemory(&servInfo, sizeof(servInfo));

servInfo.sin_family = AF_INET;
servInfo.sin_addr = ip_to_num;	  // Server's IPv4 after inet_pton() function
servInfo.sin_port = htons(1234);

erStat = connect(ClientSock, (sockaddr*)&servInfo, sizeof(servInfo));
	
	if (erStat != 0) {
		cout << "Connection to Server is FAILED. Error # " << WSAGetLastError() << endl;
		closesocket(ClientSock);
		WSACleanup();
		return 1;
	}
	else 
		cout << "Connection established SUCCESSFULLY. Ready to send a message to Server" 
    << endl;

Этап 5 (только для Сервера). Подтверждение подключения

После начала прослушивания (вызов функции listen()) следующей функцией должна идти функция accept(), которую будет искать программа после того, как установится соединение с Клиентом. Прототип функции accept():

SOCKET accept(SOCKET <"слушающий" сокет на стороне Сервера>, sockaddr* <указатель на пустую структуру sockaddr, в которую будет записана информация по подключившемуся Клиенту>, int* <указатель на размер структуры типа sockaddr>)

 Функция accept() возвращает номер дескриптора, под которым зарегистрирован сокет в ОС. Если произошла ошибка, то возвращается значение INVALID_SOCKET.

Если подключение подтверждено, то вся информация по текущему соединению передаётся на новый сокет, который будет отвечать со стороны Сервера за конкретное соединение с конкретным Клиентом. Перед вызовом accept() нам надо создать пустую структуру типа sockaddr_in, куда запишутся данные подключившегося Клиента после вызова accept(). Пример кода:

sockaddr_in clientInfo; 

ZeroMemory(&clientInfo, sizeof(clientInfo));	

int clientInfo_size = sizeof(clientInfo);

SOCKET ClientConn = accept(ServSock, (sockaddr*)&clientInfo, &clientInfo_size);

if (ClientConn == INVALID_SOCKET) {
		cout << "Client detected, but can't connect to a client. Error # " << WSAGetLastError() << endl;
		closesocket(ServSock);
		closesocket(ClientConn);
		WSACleanup();
		return 1;
}
else 
		cout << "Connection to a client established successfully" << endl;

Всё, соединение между Клиентом и Сервером установлено! Самое время попробовать передать информацию от Клиента к Серверу и обратно. Как мы в начале и договорились, мы будет реализовывать простейший чат между ними.

Этап 6: Передача данных между Клиентом и Сервером

Принимать информацию на любой стороне можно с помощью функции recv(), которая при своём вызове блокирует исполнение кода программы до того момента, пока она не получит информацию от другой стороны, либо пока не произойдет ошибка в передаче или соединении.

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

Рассмотрим прототипы функций recv() и send():

int recv(SOCKET <сокет акцептованного соединения>, char[] <буфер для приёма информации с другой стороны>, int <размер буфера>, <флаги>)

int send(SOCKET <сокет акцептованного соединения>, char[] <буфер хранящий отсылаемую информацию>, int <размер буфера>, <флаги>)

Флаги в большинстве случаев игнорируются – передается значение 0.

Функции возвращают количество переданных/полученных по факту байт.

Как видно из прототипов, по своей структуре и параметрам эти функции совершенно одинаковые. Что важно знать:

  • и та, и другая функции не гарантируют целостности отправленной/полученной информации. Это значит, что при реализации прикладных задач по взаимодействию Клиента и Сервера с их использованием требуется принимать дополнительные меры для контроля того, что все посланные байты действительно посланы и, что еще более важно, получены в том же объеме на другой стороне

  • предельно внимательно надо относиться к параметру «размер буфера». Он должен в точности равняться реальному количеству передаваемых байт. Если он будет отличаться, то есть риск потери части информации или «замусориванию» отправляемой порции данных, что ведет к автоматической поломке данных в процессе отправки/приёма. И совсем замечательно будет, если размер буфера по итогу работы функции равен возвращаемому значению функции – размеру принятых/отправленных байт.

В качестве буфера рекомендую использовать не классические массивы в С-стиле, а стандартный класс С++ <vector> типа char, т.к. он показал себя как более надежный и гибкий механизм при передаче данных, в особенности при передаче текстовых строк, где важен терминальный символ и «чистота» передаваемого массива.

Сама по себе упаковка и отправка данных делается элементарным использованием функций чтения всей строки до нажатия кнопки Ввода — fgets() с последующим вызовом функции send(), а на другой стороне — приёмом информации через recv() и выводом буфера на экран через cout <<.

Процесс непрерывного перехода от send() к recv() и обратно реализуется через бесконечный цикл, из которого совершается выход по вводу особой комбинации клавиш. Пример блока кода для Серверной части:

vector <char> servBuff(BUFF_SIZE), clientBuff(BUFF_SIZE);	
short packet_size = 0;	

while (true) {
		packet_size = recv(ClientConn, servBuff.data(), servBuff.size(), 0);					
		cout << "Client's message: " << servBuff.data() << endl; 

		cout << "Your (host) message: ";
		fgets(clientBuff.data(), clientBuff.size(), stdin);

		// Check whether server would like to stop chatting 
		if (clientBuff[0] == 'x' && clientBuff[1] == 'x' && clientBuff[2] == 'x') {
			shutdown(ClientConn, SD_BOTH);
			closesocket(ServSock);
			closesocket(ClientConn);
			WSACleanup();
			return 0;
		}

		packet_size = send(ClientConn, clientBuff.data(), clientBuff.size(), 0);

		if (packet_size == SOCKET_ERROR) {
			cout << "Can't send message to Client. Error # " << WSAGetLastError() << endl;
			closesocket(ServSock);
			closesocket(ClientConn);
			WSACleanup();
			return 1;
		}

	}

Пришло время показать итоговый рабочий код для Сервера и Клиента. Чтобы не загромождать и так большой текст дополнительным кодом, даю ссылки на код на GitHub:

Исходный код для Сервера

Исходный код для Клиента

Несколько важных финальных замечаний:

  • В итоговом коде я не использую проверку на точное получение отосланной информации, т.к. при единичной (не циклической) отсылке небольшого пакета информации накладные расходы на проверку его получения и отправку ответа будут выше, чем выгоды от такой проверки. Иными словами – такие пакеты теряются редко, а проверять их целостность и факт доставки очень долго.

  • При тестировании примера также видно, что чат рабочий, но очень уж несовершенный. Наиболее проблемное место – невозможность отправить сообщение пока другая сторона не ответила на твоё предыдущее сообщение. Суть проблемы в том, что после отсылки сообщения сторона-отправитель вызывает функцию recv(), которая, как я писал выше, блокирует исполнение последующего кода, в том числе блокирует вызов прерываний для осуществления ввода. Это приводит к тому, что набирать сообщение и что-то отправлять невозможно до тех пор, пока процесс не получит ответ от другой стороны, и вызов функции recv() не будет завершен. Благо введенная информация с клавиатуры не будет потеряна, а, накапливаясь в системном буфере ввода/вывода, будет выведена на экран как только блокировка со стороны recv() будет снята. Таким образом, мы реализовали так называемый прямой полудуплексный канал связи. Сделать его полностью дуплексным в голой сокетной архитектуре достаточно нетривиальная задача, частично решаемая за счет создания нескольких параллельно работающих потоков или нитей (threads) исполнения. Один поток будет принимать информацию, а второй – отправлять.

В последующих статьях я покажу реализацию полноценного чата между двумя сторонами (поможет разобраться в понятии «нити процесса»), а также покажу полноценную реализацию прикладного протокола по копированию файлов с Сервера на Клиент.

Mr_Dezz

Not to be confused with Windsock.

In computing, the Windows Sockets API (WSA), later shortened to Winsock, is an application programming interface (API) that defines how Windows network application software should access network services, especially TCP/IP. It defines a standard interface between a Windows TCP/IP client application (such as an FTP client or a web browser) and the underlying TCP/IP protocol stack. The nomenclature is based on the Berkeley sockets API used in BSD for communications between programs.

Early Microsoft operating systems, both MS-DOS and Microsoft Windows, offered limited networking capability, chiefly based on NetBIOS. In particular, Microsoft did not offer support for the TCP/IP protocol stack at that time. A number of university groups and commercial vendors, including the PC/IP group at MIT, FTP Software, Sun Microsystems, Ungermann-Bass, and Excelan, introduced TCP/IP products for MS-DOS, often as part of a hardware/software bundle. When Windows 2.0 was released, these vendors were joined by others such as Distinct and NetManage in offering TCP/IP for Windows.

The drawback faced by all of these vendors was that each of them used their own API (Application Programming Interface). Without a single standard programming model, it was difficult to persuade independent software developers to create networking applications which would work with any vendor’s underlying TCP/IP implementation. Add to this the fact that end users were wary of getting locked into a single vendor and it became clear that some standardization was needed.

The Windows Sockets project had its origins in a Birds of a Feather session held at Interop ’91 in San Jose on October 10, 1991.[1] It is based on socket specifications created by NetManage and which it put into public domain at this meeting. At the time the NetManage socket was the only 100% DLL-based, multi-threaded product for Windows 3.0 available. The first edition of the specification was authored by Martin Hall, Mark Towfiq of Microdyne (later Sun Microsystems), Geoff Arnold of Sun Microsystems, and Henry Sanders and J Allard of Microsoft, with assistance from many others.[citation needed] There was some discussion about how best to address the copyright, intellectual property, and potential anti-trust issues, and consideration was given to working through the IETF or establishing a non-profit foundation. In the end, it was decided that the specification would simply be copyrighted by the five authors as (unaffiliated) individuals.

All the participating developers resisted the shortening of the name to simple Winsock for a long time,[citation needed] since there was much confusion among users between the API and the DLL library file (winsock.dll) which only exposed the common WSA interfaces to applications above it. Users would commonly believe that only making sure the DLL file was present on a system would provide full TCP/IP protocol support.[citation needed]

The Windows Sockets API specification defines two interfaces: the API used by application developers, and the SPI, which provides a means for network software developers to add new protocol modules to the system. Each interface represents a contract. The API guarantees that a conforming application will function correctly with a conforming protocol implementation from any network software vendor. The SPI contract guarantees that a conforming protocol module may be added to Windows and will thereby be usable by an API-compliant application. Although these contracts were important when Windows Sockets was first released, since network environments required multi-protocol support (see above) they are now of only academic interest. Included in the Windows Sockets API version 2.0 are functions to use IPX/SPX, although the protocol was all but obsolete already at the time WSA 2.0 shipped. Microsoft has shipped the TCP/IP protocol stack with all recent versions of Windows, and there are no significant independent alternatives. Nor has there been significant interest in implementing protocols other than TCP/IP.

Windows Sockets code and design are based on BSD sockets, but provides additional functionality to allow the API to comply with the regular Windows programming model. The Windows Sockets API covered almost all the features of the BSD sockets API, but there were some unavoidable obstacles which mostly arose out of fundamental differences between Windows and Unix (though Windows Sockets differed less from BSD sockets than the latter did from STREAMS). All function calls in the API begin with the moniker WSA, e.g. WSASend() for sending data on a connected socket.

However it was a design goal of Windows Sockets that it should be relatively easy for developers to port socket-based applications from Unix to Windows. It was not considered sufficient to create an API which was only useful for newly written Windows programs. For this reason, Windows Sockets included a number of elements which were designed to facilitate porting. For example, Unix applications were able to use the same errno variable to record both networking errors and errors detected within standard C library functions. Since this was not possible in Windows, Windows Sockets introduced a dedicated function, WSAGetLastError(), to retrieve error information. Such mechanisms were helpful, but application porting remained extremely complex. Many original TCP/IP applications had been implemented by using system features specific to Unix, such as pseudo terminals and the fork system call, and reproducing such functionality in Windows was problematic. Within a relatively short time, porting gave way to the development of dedicated Windows applications.

  • Version 1.0 (June 1992) defined the basic operation of Winsock. It was kept very close to the existing interface of Berkeley sockets to simplify porting of existing applications. A few Windows-specific extensions were added, mainly for asynchronous operations with message-based notifications.
Although the document didn’t limit support to TCP/IP, TCP and UDP were the only protocols explicitly mentioned. Most vendors only delivered TCP/IP support, although Winsock from DEC included DECNet support as well.
  • Version 1.1 (January 1993) made many minor corrections and clarifications of the specification. The most significant change was the inclusion of the gethostname() function.
  • Winsock 2 was a backwards-compatible extension of Winsock 1.1. It added support for protocol-independent name resolution, asynchronous operations with event-based notifications and completion routines, layered protocol implementations, multicasting, and quality of service. It also formalized support for multiple protocols, including IPX/SPX and DECnet. The new specification allowed sockets to be optionally shared between processes, incoming connection requests to be conditionally accepted, and certain operations to be performed on socket groups rather than individual sockets. Although the new specification differed substantially from Winsock 1, it provided source- and binary-level compatibility with the Winsock 1.1 API. One of the lesser known additions was the Service Provider Interface (SPI) API and Layered Service Providers.
  • Versions 2.0.x (May 1994 onwards) had internal draft status, and were not announced as public standards.
  • Version 2.1.0 (January 1996) was the first public release of the Winsock 2 specification.
  • Version 2.2.0 (May 1996) included many minor corrections, clarifications, and usage recommendations. It was also the first version to remove support for 16-bit Windows applications.
  • Version 2.2.1 (May 1997) and Version 2.2.2 (August 1997) introduced minor functionality enhancements. Mechanisms were added for querying and receiving notification of changes in network and system configuration.
  • The IPv6 Technical Preview for Windows 2000 (December 2000) saw the first implementation of RFC 2553 (March 1999, later obsoleted by RFC 3493), a protocol-independent API for name resolution, which would become part of Winsock in Windows XP.

Updates in Windows 8


edit

Windows 8 includes the «RIO» (Registered IO) extensions for Winsock.[2]
These extensions are designed to reduce the overhead of the user to kernel mode transition for the network data path and the notification path, but use the rest of the regular Windows TCP and UDP stack (and uses existing network cards). The setup path (for example, the «connect» function) is unchanged from the regular Winsock path.

Microsoft implementations


edit

  • Microsoft did not supply an implementation of Winsock 1.0.
  • Version 1.1 of Winsock was supplied in an add-on package (called Wolverine) for Windows for Workgroups (code named Snowball). It was an integral component of Windows 95 and Windows NT from versions 3.5 and onwards (the initial commercially available version of Windows NT, version 3.1, included only a proprietary and quite incomplete implementation of TCP/IP based on the AT&T UNIX System V «STREAMS» API [citation needed]).
  • Version 2.1 of Winsock was supplied in an add-on package for Windows 95. It was an integral component of Windows 98, Windows NT 4.0, and all subsequent Windows releases. (Microsoft did not supply implementations of Winsock 2 for Windows 3.x or Windows NT 3.x.)
  • Recent versions of Winsock 2.x have been delivered with new Windows releases or as part of service packs.
  • Winsock 2 is extensible by a mechanism known as a Layered Service Provider (LSP). Winsock LSPs are available for a wide range of useful purposes, including Internet parental controls, web content filtering, QoS etc. The layering order of all providers is kept in the Winsock Catalog. In previous versions of Windows, removing a buggy LSP could result in corruption of the Winsock catalog in the registry, potentially resulting in a loss of all network connectivity. Winsock in Windows XP Service Pack 2, Windows Server 2003 Service Pack 1 and all later Windows operating systems has the ability to self-heal after a user uninstalls such an LSP.

Other implementations


edit

  • Among the other vendors offering Winsock-compliant TCP/IP and UDP/IP stacks were (alphabetically) 3Com, Beame & Whiteside, DEC, Distinct, Frontier, FTP Software, IBM, Microdyne, NetManage, Novell, Sun Microsystems and Trumpet Software International.
  • Trumpet Winsock by Peter Tattam was one of the few Winsock 1.0 implementations that could be installed under Windows 3.0, which had no built-in support for Winsock.[3][4] Trumpet was also the most popular shareware implementation of Winsock for Windows 3.x. Trumpet Winsock 5.0 is available for Windows 95/98 and Windows NT and includes a Winsock 1.1 compliant IPv6 stack for these operating systems.[5]
  • The Wine project contains a source and binary compatible reimplementation of Winsock on top of the BSD sockets API.
  • Berkeley sockets
  • Layered Service Provider (Winsock LSP)
  1. ^ «Winsock Version 1.0 Rev.A». Retrieved 8 October 2020.
  2. ^ «New techniques to develop low-latency network apps». Channel 9.
  3. ^ «Mosaic turns 20: Let’s fire up the old girl, show her the web today». theregister.co.uk.
  4. ^ «What It Was Like To Build A World Wide Web Site In 1995». fastcompany.com. 18 November 2015.
  5. ^ «Downloads». www.trumpet.com.au.
  • MSDN — Windows Socket 2 What’s New Reference
  • MSDN — Windows Socket 2 Start page
  • Sockets FAQ — Windows Sockets FAQ
  • Client / Server Programming with TCP/IP Sockets at the Wayback Machine (archived March 3, 2016) — Winsock C++ Programming
  • Porting Berkeley Socket programs to Winsock
  • Windows Network Development blog — Microsoft developer blog covering Winsock, WSK, WinINet, Http.sys, WinHttp, QoS and System.Net, with a focus on features being introduced in Windows Vista
  • Brief History of Microsoft on the Web
  • WinSock Development Information
  • Winsock Programmer’s FAQ

WinSock или Windows socket — это интерфейс программного программирования (API) созданный для реализации приложений в сети на основе протокола TCP/IP. То есть это просто группа функций !!!! Для работы используется WSOCK32.DLL.

Программа
WSOCK32.DLL
TCP/IP

Практически это интерфейс к протоколу TCP/IP.

При взаимодействии клиент — сервер в сети каждого участника взаимодействия можно рассматривать как конечную точку. Сокет это вроде как и есть эта конечная точка. В приложении Вы определяете сокет. И хоть программирование сокетов в UNIX и Windows похоже, мы с Вами будем рассматривать именно Windows socket.

Незнаю интересно это или нет, но Windows socket разрабатывался на основе интерфейса Беркли для UNIX, но к ним добавлены функции поддержки событий Windows.

Есть две версии WinSock

  • WinSock 1.1 — поддержка только TCP/IP
  • WinSock 2.0 — Поддерка дополнительного программного обеспечения

Спецификация WinSock разделяет функции на три типа:

  1. Функции Беркли
  2. Информационные функции (получение информации о наименовании доменов, службах, протоколах Internet)
  3. Расширения Windows для функций Беркли

Все функции могут быть блокирующие и неблокирующие. Обычно блокирующие это функции Беркли. То есть при работе такой функции нельзя выполнять другие функции WinSock.

Давайте расмотрим как производится подключение к серверу. Сначала программа подключается к адресу IP с созданием сокета. Программа будет ждать подключения. Для подключения программа клиент тоже создает сокет и пытается подключиться к сокету сервера. Но сервер не спит !!! Только он увидит попытку подключения он создаст новый сокет. И этот новый сокет будет использоваться для взаимодействия с клиентом. А тот, к которому была попытка подключения будет ждать следующего. На этой основе производится взаимодействие сервера и многими программами.

Сам сокет может быть создан на основе:

  1. TCP (transport control protocol) — надежное соединение
  2. UDP (user datagram protocol) — ненадежное соединения

Основная: Winsock — это программный интерфейс, поддерживающий связь между Windows и TCP / IP. Продолжайте читать этот пост, чтобы получить всю необходимую информацию о Winsock.

Оглавление

Definition

Сокращенно от Windows Sockets API (WSA), Winsock — это вспомогательная программа и техническая спецификация, которая определяет, как сетевое программное обеспечение Windows получает доступ к сетевым службам в вычислениях, особенно TCP / IP. Он обрабатывает запросы ввода и вывода для Интернет-приложений в операционной системе Windows.

Он адаптирован из Windows для интерфейса сокетов Berkeley Unix. Вот почему он называется Winsock. Сокет — это особое соглашение, которое связывает два программных процесса и обменивается данными по сети или на одном компьютере.

Фон

Проект Windows Socket зародился на конференции Birds Of A Feather 10 октября 1991 года на Interop ’91 в Сан-Хосе в Сан-Хосе. Он основан на спецификациях сокетов, созданных NetManage. И он представил эти спецификации общественному достоянию на этой встрече.

Первое издание этой спецификации было создано Мартином Холлом, Марком Тофиком из Microdyne, Джеффом Арнольдом из Sun Microsystems и Генри Сандерсом и Дж. Аллардом из Microsoft при содействии многих других.

Ведутся дискуссии о том, как лучше всего решить проблемы интеллектуальной собственности, авторского права и потенциального антимонопольного законодательства, а также рассмотрение возможности работы через IETF или создания некоммерческого фонда. В конце концов, было решено, что спецификация будет состоять только из пяти авторов с индивидуальными авторскими правами.

Долгое время все участвующие разработчики отказывались сокращать имя до простого Winsock. Потому что среди пользователей существует большая путаница между файлом библиотеки DLL (winsock.dll) и API, в то время как файл библиотеки DLL предоставляет только общий интерфейс WSA для указанного выше приложения. Пользователи обычно считают, что полная поддержка протокола TCP / IP может быть предоставлена только в том случае, если они гарантируют наличие файлов DLL в системе.

Технология

Спецификация Winsock определяет два интерфейса: API и SPI. Разработчики приложений используют первое, а второе предлагает способ добавления новых модулей протокола в систему для разработчиков сетевого программного обеспечения. Каждый интерфейс представляет собой контракт.

API гарантирует, что совместимые приложения будут работать должным образом, как это реализовано согласованным протоколом от любого поставщика сетевого программного обеспечения. Контракт SPI предоставляет совместимый с протоколом модуль, который может быть добавлен в Windows и поэтому используется API-совместимыми приложениями.

Код и конструкция сокета Windows основаны на сокетах BSD, но предлагают дополнительные функции, которые позволяют API соответствовать общей модели программирования Windows.

Windows Socket API охватывает почти все характеристики BSD socket API. Однако некоторые неизбежные препятствия проистекают прежде всего из фундаментальных различий между Windows и Unix.

Однако сокеты Windows спроектированы таким образом, чтобы разработчикам было относительно легко переносить приложения на основе сокетов из Unix в Windows. Недостаточно создать API, который работает только для недавно написанных программ Windows. В результате сокеты Windows содержат много элементов, которые предназначены для переносимости.

Это невозможно в Windows, поэтому в сокетах Windows есть особая функция WSAGetLastError () для получения сообщений об ошибках. Хотя эти механизмы полезны, перенос приложений все еще слишком сложен.

Многие из исходных приложений TCP / IP были реализованы с использованием специфических для Unix системных функций, которые проблематично воспроизвести в Windows.

Перенос уступает место разработке специализированных приложений Windows за относительно короткий период.

Реализации

Реализации Microsoft

  • Microsoft не предлагала реализацию Winsock 1.0.
  • Версия 1.1 Winsock была доступна в дополнительном пакете под названием Wolverine for Windows for Workgroups.
  • Версия 2.1 Winsock была доступна в виде дополнительного пакета для Windows 95.
  • Последние версии Winsock 2.x поставляются как часть пакетов обновления или с новыми выпусками Windows.
  • Winsock 2 можно расширить с помощью механизма, называемого многоуровневым поставщиком услуг (LSP).

Другие реализации

  • Другие поставщики, предлагающие Winsock-совместимые стеки TCP / IP и UDP / IP, включают 3Com, DEC, Beame и Whiteside, Distinctive, Frontier, IBM, FTP Software, NetManage, Novell, Sun Microsystems, Microdyne и Trumpet Software International.
  • Trumpet Winsock Питера Таттама — одна из немногих реализаций Winsock 1.0, установленных под Windows 3.0, и эта версия не имеет встроенной поддержки Winsock.
  • Проект Wine включает исходный код Winsock и двоичную совместимость, которая повторно реализована в API сокетов BSD.

Заключение

Выше представлена основная информация о Winsock, включая его определение, предысторию, технологию и ее реализации.

Introduction

Every network application that runs on Windows relies on the Windows Socket API to communicate. It is a fundamental component of networking on Windows operating systems that enables applications to send and receive data over the network. In this article, we will explore the basics of Windows Socket, its importance, and how it works.

What is Windows Socket?

Windows Socket, also known as Winsock, is a programming interface and a set of protocols that enable software applications to communicate over a network. It is a standard API (Application Programming Interface) that provides a standardized way for applications to access network services and resources. Winsock was introduced in Windows 3.1 and has been a part of every Windows operating system since then.

How does Windows Socket work?

Windows Socket uses the client-server model of communication. In this model, the application that initiates communication is the client, and the application that responds to the request is the server. The client initiates communication by creating a socket, which is an endpoint for sending and receiving data over the network. The server, on the other hand, listens for incoming requests on a specific port and responds to them accordingly.

The client and the server communicate using a protocol, which is a set of rules that govern how data is transmitted over the network. There are several protocols that Windows Socket supports, including TCP (Transmission Control Protocol), UDP (User Datagram Protocol), and ICMP (Internet Control Message Protocol).

Why is Windows Socket important?

Windows Socket is essential for any network application that runs on Windows. It provides a standardized interface for applications to access network services and resources, regardless of the underlying network protocol. Without Windows Socket, each application would have to implement its own networking code, which would be time-consuming and error-prone.

Windows Socket also provides a high level of abstraction, which means that applications do not need to know the details of the underlying network protocols. This makes it easier for developers to create network applications and ensures that they are compatible with different network environments.

Windows Socket API

The Windows Socket API is a set of functions and structures that developers use to create network applications that run on Windows. These functions and structures provide a high-level interface for accessing network services and resources, making it easier for developers to create network applications.

The Windows Socket API includes functions for creating and managing sockets, sending and receiving data, and handling errors. It also provides structures for defining socket addresses and managing network protocols.

Creating and Managing Sockets

The Windows Socket API provides several functions for creating and managing sockets. The most commonly used functions are socket(), bind(), listen(), accept(), connect(), and closesocket(). Here is a brief description of each function:

  1. socket() – creates a new socket that can be used for sending and receiving data over the network.
  2. bind() – assigns a local address to a socket.
  3. listen() – puts a socket into listening mode, waiting for incoming requests.
  4. accept() – accepts an incoming request and creates a new socket to handle the request.
  5. connect() – initiates a connection request to a remote server.
  6. closesocket() – closes a socket and releases the resources associated with it.

Sending and Receiving Data

The Windows Socket API provides functions for sending and receiving data over the network. The most commonly used functions are send(), recv(), sendto(), and recvfrom(). Here is a brief description of each function:

  1. send() – sends data over a connected socket.
  2. recv() – receives data from a connected socket.
  3. sendto() – sends data to a specific destination address.
  4. recvfrom() – receives data from a specific source address.

Handling Errors

The Windows Socket API provides functions for handling errors that occur during network communication. The most commonly used functions are WSAGetLastError() and WSASetLastError(). Here is a brief description of each function:

  1. WSAGetLastError() – retrieves the error code for the last network operation.
  2. WSASetLastError() – sets the error code for the last network operation.

Common Windows Socket Errors

Like any network communication, Windows Socket is prone to errors. Here are some of the most common errors that occur when using Windows Socket:

  1. WSAEINTR – The blocking call was canceled by an interrupting function call.
  2. WSAEBADF – The file handle is not valid.
  3. WSAEACCES – The requested operation is not allowed on a socket of this type.
  4. WSAEFAULT – The pointer passed as a parameter is not valid.
  5. WSAEINVAL – An invalid argument was passed.
  6. WSAEMFILE – No more sockets are available.
  7. WSAEWOULDBLOCK – The socket is marked as non-blocking and the requested operation would block.
  8. WSAEINPROGRESS – A blocking operation is in progress.
  9. WSAEALREADY – The operation is already in progress.
  10. WSAENOTSOCK – The file handle is not a socket.
  11. WSAEDESTADDRREQ – A destination address is required.
  12. WSAEMSGSIZE – The message is too long.
  13. WSAEPROTOTYPE – The protocol is not supported.
  14. WSAENOPROTOOPT – The option is not supported by the protocol.
  15. WSAEPROTONOSUPPORT – The protocol is not supported.
  16. WSAESOCKTNOSUPPORT – The socket type is not supported.
  17. WSAEOPNOTSUPP – The operation is not supported.
  18. WSAEPFNOSUPPORT – The protocol family is not supported.
  19. WSAEAFNOSUPPORT – The address family is not supported.
  20. WSAEADDRINUSE – The address is already in use.
  21. WSAEADDRNOTAVAIL – The address is not available.
  22. WSAENETDOWN – The network is down.
  23. WSAENETUNREACH – The network is unreachable.
  24. WSAENETRESET – The network connection was reset.
  25. WSAECONNABORTED – The connection was aborted.
  26. WSAECONNRESET – The connection was reset.
  27. WSAENOBUFS – No buffer space is available.
  28. WSAEISCONN – The socket is already connected.
  29. WSAENOTCONN – The socket is not connected.
  30. WSAESHUTDOWN – The socket has been shut down.
  31. WSAETOOMANYREFS – Too many references to a kernel object.
  32. WSAETIMEDOUT – The connection timed out.
  33. WSAECONNREFUSED – The connection was refused.
  34. WSAELOOP – Cannot translate name.
  35. WSAENAMETOOLONG – Name too long.
  36. WSAEHOSTDOWN – The host is down.
  37. WSAEHOSTUNREACH – The host is unreachable.
  38. WSAENOTEMPTY – Directory not empty.
  39. WSAEPROCLIM – Too many processes.
  40. WSAEUSERS – Too many users.
  41. WSAEDQUOT – Disc quota exceeded.
  42. WSAESTALE – Stale NFS file handle.
  43. WSAEREMOTE – Too many levels of remote in path.

Conclusion

Windows Socket is a fundamental component of networking on Windows operating systems. It provides a standardized interface for applications to access network services and resources, making it easier for developers to create network applications. Windows Socket uses the client-server model of communication and supports several protocols, including TCP, UDP, and ICMP. Understanding the basics of Windows Socket and its importance is essential for anyone who develops network applications on Windows.

FAQ

What is Winsock?

Winsock is another name for Windows Socket, which is a programming interface and a set of protocols that enable software applications to communicate over a network.

What is a socket?

A socket is an endpoint for sending and receiving data over the network.

What is a protocol?

A protocol is a set of rules that govern how data is transmitted over the network.

What are the most common Windows Socket errors?

Some of the most common errors that occur when using Windows Socket include WSAEWOULDBLOCK, WSAECONNABORTED, WSAECONNRESET, WSAETIMEDOUT, and WSAECONNREFUSED.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как сделать так чтобы ноутбук не уходил в спящий режим при бездействии windows 10
  • Windows 10 symlink на папку
  • Как снять пароль с компьютера windows 10 через командную строку
  • Обновить сертификаты безопасности на старом устройстве с windows xp
  • Windows посмотреть mac адреса в сети