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

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

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

Практически это интерфейс к протоколу 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) — ненадежное соединения

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

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

Понятие windows sockets приложения

Что такое сокет — это по сути область оперативной памяти, в которой на определенном сетевом порту (TCP/UDP) работает приложение, и именно оно прослушивает нужный порт. Какая задача стояла перед программистами, задача простая переместить информацию из оперативной памяти одного компьютера, в оперативную память другого компьютера. Дальше это может быть представлено как:

Номер сокета Windows, это номер ячейки оперативной памяти к которому привязано приложение. Приложение привязавшись к некой области оперативной памяти начинает туда писать данные и сокет из этой области памяти начинает мелкими пакетами по 65 кбайт, начинает передавать в сеть на другое устройство. На другой стороне эти кусочки, так же помещаются в ОЗУ, желательно в той же последовательности, и сокет с той стороны начинает их разбирать, и представлять пользователю из какого то приложения.

Список сокетов приложений в Windows

У меня стоит операционная систем Windows 8.1, показывать я буду все на ней, в прошлый раз мы кстати в ней лечили баг, что был не найден run vbs. Для того, чтобы посмотреть какие сокеты соответствуют каким приложениям и каким TCP/UDP портам, вы должны перейти в директорию

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

Открыв данный файл вы увидите название службы (приложения) номер сокета (TCP/UDP) и описание. Для примера видно, что сервер ftp работает по портам 20 и 21. По сути тут системе и задаются стандарты по которым должны работать службы.

Как посмотреть сокеты приложений у вас на компьютере

Тут два метода которыми я пользуюсь. Представим себе ситуацию, что вы установили некое приложение, все работает пытаетесь на него попасть с другого компьютера по сети, но не можете. Отключаете брандмауэр на том компьютере, и все начинает работать, вывод блокируется какой то порт этого приложения. Его вычислить поможет нам две утилиты, первая из командной строки, а вторая имеет удобный графический интерфейс.

Более подробно про утилиту netstat и ее использование читайте по ссылке. В итоге вы получите сводную таблицу, в которой будет вот, что интересно:

  • Тип протокола — TCP или UDP
  • Адрес отправителя с указанием портов
  • Адрес получателя с указанием портов
  • Состояние — либо слушает либо установил соединение и закрыто
  • PID это номер идентифицирующий приложение

Как видите в примере у меня много сессий по 443 и 80 порту по сути это браузер Google Chrome.

Приложение заняв сокет, уже не позволит на нем же открыться другому приложению, Сокет живет минут 10.

Как изменить время жизни сокета

Для того, чтобы в операционной системе Windows изменить TTL или как его еще называют время жизни сокета, вам необходимо воспользоваться реестром. Открываете редактор реестра Windows 8.1. Переходите в раздел

Там есть ключ TcpTimedWaitDelay, если его нет то нужно его создать. Укажите нужное вам десятичное значение. TcpTimedWaitDelay — Этот параметр определяет интервал времени, в течение которого подключение находится в состоянии TIME_WAIT, прежде чем будет закрыто. Пока подключение находится в состоянии TIME_WAIT, пара сокетов не может быть использована повторно (это т. н. «состояние 2MSL»). Согласно документу RFC793, данное значение должно в два раза превышать максимальное время жизни пакета в сети.

Как узнать PID приложения

Для того, чтобы узнать PID приложения в Windows, вам нужно в области пуск кликнуть правой кнопкой мыши и из контекстного меню выбрать Диспетчер задач

В диспетчере задач, найдите поле ИД процесса .если его не будет то добавьте.

Теперь давайте смотреть, в правой части я вижу приложение skype и оно имеет PID 4352, смотрим в левой части экрана и видим порты и Ip адрес, которые слушает данной приложение.

Ну и еще есть утилита TCPView, про нее я уже отдельно писал. Утилита бесплатная и имеет графический интерфейс, запустив ее вы сразу видите кому какой PID принадлежит. Так же видно все сокеты и их состояния.

Думаю, у вас теперь не должно быть вопроса, что такое сокеты windows и как их посмотреть, всем спасибо за прочтение.

сокеты Sockets

Пространство имен System.Net.Sockets содержит управляемую реализацию интерфейса Windows Sockets. The System.Net.Sockets namespace contains a managed implementation of the Windows Sockets interface. Все остальные классы для доступа к сети в пространстве имен System.Net основываются на этой реализации сокетов. All other network-access classes in the System.Net namespace are built on top of this implementation of sockets.

Класс Socket платформы .NET Framework — это версия служб сокетов на основе управляемого кода, предоставляемая API Winsock32. The .NET Framework Socket class is a managed-code version of the socket services provided by the Winsock32 API. В большинстве случаев методы класса Socket просто маршалируют данные в аналогичные собственные методы Win32 и осуществляют все необходимые проверки безопасности. In most cases, the Socket class methods simply marshal data into their native Win32 counterparts and handle any necessary security checks.

Читайте также:  Как запустить виндовс через линукс

Класс Socket поддерживает два основных режима: синхронный и асинхронный. The Socket class supports two basic modes, synchronous and asynchronous. В синхронном режиме при вызове функций, выполняющих сетевые операции (например, Send и Receive), ожидается завершение операций, прежде чем управление возвращается вызывающей программе. In synchronous mode, calls to functions that perform network operations (such as Send and Receive) wait until the operation completes before returning control to the calling program. В асинхронном режиме вызовы возвращаются немедленно. In asynchronous mode, these calls return immediately.

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

Теория применения сокетов совсем недавно была описана в статье “Сокеты M$ Windows”, которую вы можете легко найти в разделе “Статьи/Сеть”. Не будем повторяться, но вкратце скажем, что сокеты определяют логику для программирования сети аналогичную работе с файлами. В разделе “Исходники/Сеть и коммуникации” уже давно (со времен wasm.zite.ru) имеется рабочая небольшая программа “ledilog.zip\connect.asm”, в которой на основе использования сокетов реализован обмен текстовыми сообщениями между двумя компьютерами в сети. Таким образом, накопилась критическая масса, состоящая из некоторого минимума теории и кое-каких практических материалов. Все это и подтолкнуло автора к использованию в своем проекте (детали в данном случае не важны) связи по локальной сети между компьютерами на основе сокетов MS Windows. Однако все оказалось не так просто, как хотелось. Впрочем, как и всегда.

Куски кода, связанные с созданием и использованием сокетов из программы-оригинала легко переносились и компилировались, но все работало не так, как надо, либо вообще не работало. Обнаружились значительные провалы между кажущимся пониманием теории и практикой, к тому же комментарии у источника были на итальянском языке, что не добавляло ясности. Пришлось отказаться от первоначальной идеи и писать отдельную программку с минимумом интерфейса специально для проверки, что ж это за зверь такой: сокеты Windows. В данной статье приведена попытка описать полученный опыт на примере реальной, хотя и учебной программы. Тут не будет много теории, только необходимый для понимания кода минимум. Также предполагается, что читатель уже знаком с тем, как создавать приложение под Windows, имеющее основное окно и процедуру этого окна, как вызываются диалоговые окна. И последнее, так уж получилось, что моя программа внешне вышла очень похожей на программу-оригинал. Не судите меня строго.

Для впервые заинтересовавшихся сетевым программированием есть смысл пояснить, что же из себя представляют сокеты. Сокет можно рассматривать, как конечный пункт передачи данных по сети. Сетевое соединение — это процесс передачи данных по сети между двумя компьютерами или процессами. Тогда сокет — конечный пункт такой передачи данных. Другими словами, когда программы используют сокет, для них он является абстракцией, представляющий одно из окончаний сетевого соединения. Для установления соединения в абстрактной модели сокетов необходимо, чтобы каждая из сетевых программ имела свой собственный сокет. Недаром слово socket переводится с английского как гнездо или разъем!

Связь между двумя сокетами может быть ориентирована на соединение, а может быть и нет. С чем это едят? Все дело в том, в сетевом протоколе TCP/IP (а на сегодня это “родной” протокол интернета, да и большинства локальных сетей) предусмотрено два режима: ориентированный и не ориентированный на соединение. В ориентированных на соединение протоколах данные перемещаются как единый, последовательный поток байт без какого либо деления на блоки. Конечно, имеется в виду логика процесса, а не то, что физически происходит в среде передачи. В не ориентированных на соединение протоколах сетевые данные перемещаются в виде отдельных пакетов, называемых датаграммами. Как мы уже говорили, сокеты могут работать как с одними, так и с другими. В дальнейшем при создании сокета мы с этим столкнемся. А сейчас достаточно запомнить, что датаграммы могут приходить к получателю не подряд, а в непpедсказуемой последовательности. Так что датаграммы мы использовать в данном примере не будем, а только режим, ориентированный на соединение!

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

Несмотря на то, что первоначально сокеты появились в системе UNIX (т.н. сокеты Беркли), на данный момент разработчики Windows давно модифицировали и расширили интерфейс для работы сокетов. Таким образом, сейчас мы имеем многочисленные функции API, так или иначе связанные с сокетами:

WSAStartup()* инициализирует Windows Socket dll
WSACleanup()* прекращает использование этой dll
socket()* функция создает сокет с заданными параметрами
WSAAsyncSelect()* функция указывает посылать сообщение от
сокета заданному окну при любом из
заданных сетевых событий
bind()* ассоциирует локальный адрес с сокетом
listen()* устанавливает сокет в состояние, в котором он
слушает порт на предмет входящих соединений
accept()* функция извлекает из очереди ожидающих
подключений первое, создает новый сокет и
возвращает его дескриптор
connect()* функция подключает созданный сокет к
указанному адресу
select() функция определяет статус одного или более
сокетов
shutdown() функция запрещает посылать и/или принимать
данные от сокета
ioctlsocket() функция управляет режимом сокета
getsockopt() функция возвращает установки сокета
recv()* функция получает данные от сокета
send()* функция посылает данные в ранее
подключенный сокет
sendto() функция посылает данные по указанному адресу
recvfrom() функция получает датаграммы от сокета

Звездочками отмечены те функции, которые будут встречаться в тестовой программе. Учтите, что кроме перечисленных существуют и многие другие… А теперь приступим к более подробному рассмотрению того, как этим хозяйством пользоваться. Скачайте пример здесь. Программа начинается как обычно с подключения необходимых библиотек, имеет секцию инициализированных и неинициализированных данных (.data и .data?). Обратите внимание на задание констант. Все константы (определение использованных ресурсов и др.) вынесены в отдельный файл SocSoc.inc и они нам в этот раз не интересны. Другое дело строка:

Это задание численного значения сообщения WM_SOCKET, того самого сообщения, которое нам в дальнейшем будет посылать Windows при работе с сокетами. Дело в том, что Windows не использует для своих стандартных сообщений значения выше WM_USER, поэтому мы легко можем использовать этот диапазон для нужд своего приложения. Отметим этот важный момент, в дальнейшем мы еще раз вернемся к обсуждению сообщений типа WM_USER+.

Секция кода начинается с определений макросов, используемых при анализе сообщений нашим окном. Конечно, надо бы вынести макросы в отдельный файл .inc – файл и подключить его с помощью include. Но в данном случае их всего два и хотелось максимально упростить для понимания начинающими этот проект. Только поэтому макросы помещены в начало секции .code. Ну не данные же это в самом деле! Так что не делайте, как я.

Cначала опишем вкратце общий алгоритм работы нашей программы, а затем приступим к подробному анализу кода:

Читайте также:  Как узнать свою версию java windows 10

1) при запуске получаем и сохраняем хэндл программы, регистрируем у Windows текстовую строку в качестве сообщения и сохраняем возвращенный нам код сообщения для дальнейшего использования (об этом позже);

2) инициализируем dll, ответственную за использование сокетов Windows;

3) если получена ошибка инициализации, то делать дальше нечего – выходим с ошибкой из программы! Если же вызов dll прошел успешно, то продолжим работу: получаем адрес командной строки, (если таковая была при запуске – в данном примере не используется). Вызываем функцию WinMain – которая, собственно и определяет логику работы приложения и которая будет подробно рассмотрена ниже;

4) после выхода из WinMain возвращаемся в Windows.

А теперь разберем, что происходит в третьем пункте. В объявлении функции WinMain все достаточно традиционно и подробный анализ пропускаем. Для нас интерес составляет процедура WndProc главного окна программы, которая получает и реагирует на сообщения Windows. Сразу же после создания нашего окна процедура WndProc получит соответствующее сообщение: WM_CREATE. Это удобный момент для приведения в исходное состояние всего нашего хозяйства. Раз мы собираемся обмениваться с другими компьютерами, хорошо бы узнать кое-что и о себе, вернее о том компьютере, где запущен экземпляр нашей программы. Можно получить имя компьютера в виде текстовой строки в buffer соответствующей функцией, а затем оттуда скопировать в выходной буфер:

Аналогично получаем IP адрес компьютера по имени:

Для этого есть в API специальная функции gethostbyname, которая возвращает информацию о компьютере по его имени, заполняя специальную структуру hostent. Приведем ее для лучшего понимания дальнейших действий:

Элемент структуры h_name – не что иное, как указатель на строку с именем нашего компьютера. А вот элемент h_list более интересен! Это указатель на список IP-адресов компьютера. Их может быть несколько, по числу сетевых интерфейсных карт, установленных в компьютере. Причем адреса представлены в сетевом порядке байт. Нас интересует первый из них. Вот как добраться до этого адреса:

После преобразования функцией inet_ntoa, сохраняем полученный строковый формат IP адреса (вида 127.0.0.1) в еще один выходной буфер. Во всем этом есть один тонкий момент, непонимание которого может привести к дальнейшему использованию неправильных данных! Те функции Windows Sockets API, которые возвращают указатели на различные данные (а это часто так и есть) гарантирует их (данных) сохранность только до следующего вызова функций Sockets API. Поэтому необходимо сразу же копировать все необходимые нам значения в отведенные нашей программой для этого переменные! Это в полной мере относится и к функции gethostbyname.

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

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

Итак. Сначала нам нужно открыть сокет:

AF_INET – семейство, в версии 1.1 только AF_INET;

SOCK_STREAM — тип сокета, который вы желаете использовать.

Помните, мы выбираем связь, ориентированную на соединение, и говорим НЕТ датаграммам (SOCK_DGRAM);

0 – протокол, не устанавливать никакого протокола.

И если нет ошибки, сохранить его дескриптор для дальнейшего использования:

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

где hSocket2 — дескриптор сокета (вот сразу и пригодился)

hWnd — дескриптор главного окна приложения

WM_SOCKET — сообщение, нами же определенное

FD_ACCEPT+FD_READ – маска, задающая интересующие нас сообщения от этого сокета (в данном случае мы хотим получать уведомление о попытке подключения и уведомление о готовности данных для чтения).

Затем приступаем к уточнению деталей. Для этого сначала надо преобразовать номер порта в так называемый сетевой порядок байт. Хорошо, что для этого есть специальная API-функция. Воспользуемся ей и заполняем структуру другими необходимыми параметрами:

Далее необходимо сопоставить локальный адрес, представленный в структуре с ранее открытым сокетом:

И последнее, теперь надо заставить сокет слушать указанный порт на предмет входящих сообщений:

Где указываем, естественно, дескриптор сокета и некое число, определяющее максимальную длину очереди ожидаемых подключений. Так что число пять просто перекочевало из программы – оригинала. Поставьте десять, если это нужно. На этом, собственно, и заканчивается настройка сокета на прием, т.е. слушающего указанный порт.

Затем, если пользователь отважится и выберет пункт меню “Подключить”, то создаем диалоговое окно выбора IP адреса подключения:

После выхода из которого (если адрес был указан) приходит пора создавать сокет на передачу:

Здесь пока все тоже, что и ранее с первым сокетом, только теперь нас интересуют сообщение о состоявшемся подключении и уведомление о закрытии сокета (FD_CONNECTи FD_CLOSE).

Далее по аналогии формируем структуру , содержащую адрес подключения:

Тут немного пояснений. После выхода из диалогового окна выбора адреса в буфере AdresIP содержится IP-адрес в привычном для нас виде a.b.c.d. Для удобства отладки приложения указан и адрес “самого себя”. Это — 127.0.0.1. Дело в том, что согласно соглашениям TCP гарантируется, что все пакеты на все адреса, начинающиеся со 127.ххх в физическую линию передаваться не будут. Таким образом, это сильно облегчает жизнь тем людям, у которых нет возможности все время сидеть на двух компьютерах в сети сразу. Пример полностью работает и на ОДНОМ компьютере. Только адрес надо предварительно преобразовать функцией inet_addr из строкового формата с точками, а потом уже заносить в .

И апофеоз, надо подключить созданный сокет к указанному в IP- адресу:

Вот после этих строк процедура главного окна получит сообщение от Windows: WM_SOCKET с lParam = FD_CONNECT. Тут самое время сообщить о состоявшемся (или нет) соединении с помощью простого MessageBox-а. Ничего дополнительно делать не надо.

Что же произойдет, когда слушающий сокет обнаруживает попытку соединения? Не забывайте, что мы можем коннектиться к самим себе, но это существа дела не меняет. Все просто. При наступлении какого-либо события, связанного с сокетом, Windows шлет сообщение процедуре главного окна, в данном случае пошлет тот же WM_SOCKET, теперь уже с параметром FD_ACCEPT. Делать нечего, нужно вызвать специальную функцию API, чтобы разрешить входящее соединение:

Будьте бдительны! Это еще один важный момент, который в свое время попортил мне немало нервов. Конечно, входящее соединение надо сначала разрешить, а если мы не прореагируем на попытку соединения, то следующего такого сообщения от сокета больше не получим. Но более того, возвращаемое функцией accept значение представляет из себя дескриптор НОВОГО сокета, который мы должны будем далее использовать для приема данных. Его, конечно, надо сохранить. И именно его использовать в функции приема данных! Первоначальный слушающий сокет остается открытым.

Теперь о том, как передать данные, если уж связь налажена. Специально в программе есть два места, откуда можно передавать. Это и главное окно, пункт меню “Передать…”, и диалоговое окно приема/передачи. Рассмотрим второе. Это участок процедуры DlgProcZ1 диалогового окна:

При нажатии кнопки “Отослать” проверяем, установлено ли уже соединение и если да, то получаем с элемента редактирования текста IDC_EDIT02 собственно текст (до 64 байт) в буфер BytSend. Проверяем длину строки. И передаем весь буфер в сокет. Функция send имеет следующие параметры:

Читайте также:  Лучшие офлайн переводчики для windows

hSocket – дескриптор (раннее подключенного функцией connect) сокета

addr BytSend – указатель на передаваемый буфер

64 – длина буфера

0 — флаг, определяющий поведение функции (для нас только такой).

Сразу же не забудем проверить признак ошибки при передаче. Мало ли чего!

А что же прием? Если мы (или какой-нибудь другой компьютер) прислали данные на слушающий сокет, для которого была выполнена функция accept (помните, мы сохраняли дескриптор в hClient), опять процедуре главного окна летит сообщение WM_SOCKET уже c параметром FD_READ. Вот кусок соответствующего кода:

Ну, с функцией собственно приема recv, надеюсь ясно. Параметры аналогичны функции send:

hClient – дескриптор сокета (ранее полученный функцией accept!)
addr BytRecu – указатель на приемный буфер
64 – длина этого буфера
0 — флаг (для нас такой).

Далее наступает ключевой момент. Теперь, когда принятые данные уже в буфере BytRecu, пришла пора еще одного трюка.

Картинка у меня долго не складывалась, пока не появилась статья от CyberManiac (см. “Статьи/Секреты Win32/IPC”). Посвящена она механизму обмена данными между приложениями (Interprocess communication, сокращенно – IPC). Почитайте. Но у нас ситуация несколько иная. Приложение у нас одно и в данном случае не надо пересылать данные. Пусть они себе лежат в буфере. Надо всего лишь подать сигнал процедуре диалогового окна приема/передачи о факте приема от сокета. А как? Сокет–то шлет сообщения главному окну, а индицируем принятые данные в другом, диалоговом, которое ничего не знает. Да и самого диалогового окна приема/передачи в момент приема данных может не быть на экране. Но нас это не сильно беспокоит, не хотите – не надо. Наше дело сообщить. Посылаем широковещательное сообщение всем окнам функцией SendMessage. Параметры следующие:

А вот и часть кода в процедуре окна DlgProcZ1, ответственная за прием такого сообщения:

Можно заметить, что не анализируется wParam и lParam. Нам достаточно только факта самого сообщения. А теперь рассмотрим, как все-таки регистрировалось сообщение MessageIPC при входе в программу. Для этого надо было придумать уникальную текстовую строку:

Это своего рода пароль для разных приложений, по которому они могут узнавать “свое” сообщение. Такой себе “у вас продается славянский шкаф?”. Далее надо провести собственно регистрацию:

И на выходе, если eax не равно нулю, значит ошибки нет и там содержится код сообщения. Какой он? Но мы же не хотим, знать больше, чем положено. Надо просто запомнить его и использовать по мере надобности:

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

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

Менее очевидный момент заключается в том, что надо закрыть сокет на передачу, если получено сообщение о разрыве связи с приемного конца. Вот часть разбора сообщения WM_SOCKET в процедуре главного окна:

И еще. Возвращаемся к обсуждению сообщений типа WM_USER+… Цитата из CyberManiac-а: “…в некоторых программах для обмена информацией используются сообщения WM_USER+N, в частности, именно так реализован механизм IPC в WinAmp. Однако Microsoft имеет по этому поводу свое особое мнение — согласно MSDN, сообщения от WM_USER+0 до WM_USER+3FFFh включительно используются только для передачи данных внутри или между окнами одного класса.” Так что одно дело получать сообщения в процедуре окна от сокетов Windows, и совсем другое, слать IPC широковещательные сообщения с WM_USER+… в качестве параметра.

Все происходящее при открытии/закрытии сокетов очень удобно наблюдать при помощи утилиты Tcpview.exe (Mark Russinovich — www.sysinternals.com). Рекомендую! Хорошо видны порты, а также протоколы, их использующие… В частности, хорошо отслеживается эффект “расщепления” сокета на два после выполнения функции accept. Кстати, появляется еще один (кроме первоначального 3030) используемый порт, что-нибудь типа 30хх, в зависимости от наличия свободных.

Подведем итог. Для того, чтобы организовать обмен информацией между двумя компьютерами в сети, в программе создается два сокета, используемые раздельно для приема и для передачи. Имеется главное окно приложения и в разных местах программы могут создаваться два диалоговых окна. Сокеты создаются в процедуре главного окна, но это не принципиально. Существенно важно то, что оба они при наступлении соответствующих событий посылают предопределенное нами самими сообщение WM_SOCKET именно главному окну. Где в цикле разбора сообщений от Windows уже анализируются и обрабатываются… Таким образом, ВСЯ работа с сокетами сосредоточена в процедуре главного окна. Существует затруднение, состоящее в том, что данные, полученные с сокета на прием, могут быть нужны нам в диалоговом окне приема/передачи, которое у нас не получает соответствующего сообщения от сокетов Windows. Вопрос решается с помощью посылки главным окном широковещательного сообщения о факте приема данных всем другим окнам. Диалоговое окно (или другое приложение, если захотите) может легко получить такое сообщение и обработать… Конечно, это не единственный способ взаимодействия между главным окном и диалоговым. Но соль в данном случае в том, что при поступлении данных от сокета диалогового окна-то может и не быть. Поэтому был выбран путь, когда программа просто сигнализирует о факте приема данных от сокета, а далее уже не важно, нужны они кому-нибудь, или нет.

В описываемом примере было рассмотрено использование только некоторых основных функции API, ответственных за работу с сокетами Windows, в основном разобраны их параметры, кроме тех, значение которых не критично. Но! Возникает (у меня, по крайней мере) несколько вопросов. Ну, во-первых, номер порта. Какой он может быть? А должен? Какие правила на этот счет. Кроме тех, которые широко известны: 80 порт для HTTP и др. Конечно, Windows при попытке создать сокет с уже используемым портом вернет код ошибки. Попробуйте запустить два экземпляра тестовой программы! Но разве от этого легче? Можно, конечно, в программе перебирать номера, но как тот, другой компьютер узнает, чем сердце успокоилось?
Во-вторых, понятно, почему используется два раздельных сокета. Чтобы можно было независимо передавать данные и читать их тогда, когда они поступают извне. А как можно обойтись одним сокетом? Если уж действительно сокеты задают логику работы с сетью, аналогичную работе с файлами, то хорошо было бы и писать, и читать, работая с одним “файлом”. И более того. Что делать, когда надо посылать сообщения нескольким компьютерам, например, десяти… Создавать десять сокетов или перебирать один с разными IP–адресами по очереди? Что-нибудь типа широковещательного сообщения? Вообще, тот же пример, расширенный на n-компьютеров, где каждый может обмениваться с каждым, выглядит пока туманно. Более или менее ясно, как на один слушающий сокет принимать входящие с разных адресов. Не зря же мы писали: invoke listen, hSocket2, 5. 5! Хотя программа все равно могла сохранить только один дескриптор сокета после invoke accept…

Подводя итог итогам, можно сказать, что вопросы остаются. Надеюсь, что новичкам в работе с сокетами пример пригодится, а если появятся работающие ответы на вопросы (эти и другие), то будет и продолжение…

Оцените статью