Разработка приложений по технологии "клиент-сервер"
Характеристика модели клиент-сервер как технологии взаимодействия в информационной сети. Разработка и описание алгоритмов работы приложений на платформе Win32 в среде Microsoft Visual Studio, использующих для межпроцессного взаимодействия сокеты.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 02.06.2014 |
Размер файла | 544,6 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
4
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
РЕФЕРАТ
клиент сервер приложение сокет
Пояснительная записка содержит: страницы, иллюстраций, таблицы, приложения.
Цель работы: разработка приложений по технологии «клиент-сервер» для исследования взаимодействия между процессами через сокеты.
В курсовой работе разработано 3 приложения на платформе Win32 в среде Microsoft Visual Studio, использующие для межпроцессного взаимодействия сокеты. Приложение-сервер реализует выполнение следующих функций: создание сокетов, получение данных от приложений-клиентов, вывод полученных данных на экран. Приложения-клиенты реализуют выполнение следующих функций: открытие сокета, установка связи с сервером, подготовка и передача данных в соответствии с заданием.
Приложения разработаны на основе языка С++ и базовых функций Win32 API.
Выполнено определение области применения, достоинств и недостатков архитектуры «клиент-сервер»; сделан обзор системных средств коммуникации и синхронизации процессов.
WIN32 API, СОКЕТ, ПРОЦЕССЫ, СОБЫТИЯ, ПОРТ, СИНХРОНИЗАЦИЯ ПРОЦЕССОВ, АЛГОРИТМ, ПРОГРАММА.
ВВЕДЕНИЕ
Клиент - серверные приложения - это приложения, основанные на сетевой архитектуре различной связности, соединяющей для выполнения прикладных задач различные устройства, каждое из устройств может выполнять роль клиента либо сервера. Клиент-серверные приложения активно применяются в бизнесе, на предприятиях и других организациях для обеспечения рабочего процесса, наделения сотрудников удобными рабочими инструментами, и, как следствие, повышения отдачи от труда.
Рано или поздно может наступить момент, когда единственным вариантом для дальнейшего развития автоматизированных систем управления предприятием станет архитектура клиент-сервер. Архитектура клиент-сервер становится жизненно необходимой, когда число пользователей одновременно активно пользующихся одними и теми же данным превышает 10-15 человек. Если перед предприятием встает задача построения системы, в которых число мест, одновременно активно работающих с данными, превышает 20, практически единственным вариантом для него является клиент-сервер.
В курсовой работе разработано 3 приложения, приложение-сервер и 2 приложения-клиента, реализованных на языке С++ с использованием базовых функций Win32 API. С++ - это язык программирования, который был разработан для обеспечения глубокого и детального контроля процесса разработки. Win32 API - набор базовых функций интерфейсов программирования приложений операционных систем семейств Microsoft Windows корпорации «Майкрософт». Приложения созданы в Microsoft Visual Studio 2010 Professional. Microsoft Visual Studio -- линейка продуктов компании Майкрософт, включающих интегрированную среду разработки программного обеспечения и ряд других инструментальных средств.
1. ОСНОВНАЯ ЧАСТЬ
1.1 Постановка задачи
В соответствии с заданием нужно разработать 3 отдельных приложения. Приложение-сервер должно выполнять такие функции: создание сокетов, получение данных от приложений-клиентов, вывод на экран полученных данных. Приложение-клиент 1 должно выполнять такие функции: открытие сокета, установка связи с сервером, подготовка и передача серверу таких данных: системные цвета 2-х элементов окна приложения, код раскладки клавиатуры. Приложение-клиент 1 должно выполнять такие функции открытие сокета, установка связи с сервером, подготовка и передача серверу таких данных: идентификатор текущего процесса, дескриптор текущего процесса. Приложения должны бать разработаны по технологии «клиент-сервер». Метод коммуникации между процессами - сокеты.
1.2 Краткие теоретические основы разрабатываемой темы
Модели клиент-сервер - это технология взаимодействия в информационной сети. Сервер обладает правом управления тем или иным ресурсом, а клиент - пользования им. Понятия "клиент" и "сервер" описывают лишь распределение ролей при выполнении конкретной задачи, но не какие либо отдельные виды компьютеров или программ. На одном и том же компьютере могут одновременно работать программы, выполняющие как клиентские, так и серверные функции.
Каждый конкретный сервер определяется видом того ресурса, которым он владеет. Этот принцип распространяется и на взаимодействие программ. Программа, выполняющая предоставление соответствующего набора услуг, рассматривается в качестве сервера, а программы, пользующиеся этими услугами, принято называть клиентами. Программы имеют распределенный характер, т.е. одна часть функций прикладной программы реализуется в программе-клиенте, а другая - в программе-сервере, а для их взаимодействия определяется некоторый протокол. Программа клиент взаимодействует с сервером, используя определенный протокол, устанавливающий правила обмена данными. Клиент может запрашивать с сервера какие либо документы, манипулировать данными непосредственно на сервере, запускать на нем новые программы и т. п. Полученные от сервера данные клиент может предоставлять пользователю или формировать на их основе новый запрос. Клиент и сервер могут работать как на одном и том же компьютере, так и на разных. Во втором случае для обмена информацией между ними используется сетевое соединение.
Стандартные клиент-серверные приложения по своей архитектуре являются двухуровневыми. Компоненты, отвечающие за презентационный сервис и прикладную логику, размещаются на клиентской машине и обращаются к общему источнику данных по сети. В таких приложениях пользовательский интерфейс и прикладная логика образуют один уровень на клиентском компьютере, а сервисы данных предоставляются отдельными приложениями. Двухуровневые приложения хорошо работают в масштабах подразделения при наличии умеренного количества пользователей (до 100) и быстродействующей защищенной сети. Отладку приложений клиент-сервер возможно производить на локальном компьютере.
Преимущества клиент-серверной архитектуры:
ѕ делает возможным, в большинстве случаев, распределение функций вычислительной системы между несколькими независимыми компьютерами в сети. Это позволяет упростить обслуживание вычислительной системы. В частности, замена, ремонт, модернизация или перемещение сервера не затрагивают клиентов;
ѕ все данные хранятся на сервере, который, как правило, защищён гораздо лучше большинства клиентов. На сервере проще обеспечить контроль полномочий, чтобы разрешать доступ к данным только клиентам с соответствующими правами доступа;
ѕ позволяет объединить различные клиенты. Использовать ресурсы одного сервера часто могут клиенты с разными аппаратными платформами, операционными системами и т. п.
Недостатки клиент-серверной архитектуры:
ѕ неработоспособность сервера может сделать неработоспособной всю вычислительную сеть;
ѕ поддержка работы данной системы требует отдельного специалиста -- системного администратора;
ѕ высокая стоимость оборудования.
1.2.1Непосредственная коммуникация процессов
При непосредственной коммуникации (direct communication) процессы именуют друг друга явно - по именам или по адресам (указателям), которые указываются в вызовах коммуникационных примитивов, например:
ѕ send (P, message) - послать сообщение процессу P;
ѕ receive (Q, message) - получить сообщение от процесса Q.
При данном способе коммуникации свойства линии связи следующие:
ѕ связь устанавливается автоматически (ее реализуют операционная система или отдельные коммуникационные инструменты);
ѕ связь ассоциируется только с одной парой взаимодействующих процессов;
ѕ между каждой парой процессов всегда только одна связь;
ѕ связь может быть ненаправленной, но, как правило, она двунаправленная (процесс может получить сообщение от другого явно заданного процесса и принять от него сообщение).
1.2.2 Косвенная коммуникация процессов
При косвенной коммуникации (indirect communication) сообщения направляются и получаются через почтовые ящики (mailboxes), или порты (ports) - системные структуры, предназначенные для приема, хранения и передачи сообщений. Для определенности будем использовать термин почтовый ящик.
При косвенном способе коммуникации процессы используют набор операций вида:
ѕ создать новый почтовый ящик;
ѕ отправить (принять) сообщение через почтовый ящик;
ѕ удалить почтовый ящик
Основные операции коммуникации принимают вид:
ѕ send (A, message) - послать сообщение в почтовый ящик A;
ѕ receive (A, message) - получить сообщение из почтового ящика A.
1.2.3 Буферизация и очередь сообщений
С коммуникационной линией связывается очередь сообщений, реализованная одним из трех возможных способов:
ѕ нулевая емкость очереди сообщений означает, что сообщения не могут храниться в очереди. Поэтому при использовании данного способа отправитель должен ждать получателя;
ѕ ограниченная емкость очереди сообщений - конечная длина очереди, в которой может храниться максимум n сообщений. Данный способ является общеупотребительным, однако в данном случае, как уже отмечалось, необходимо предотвратить опасность атаки "buffer overrun", т.е. в любой операции проверять длину буфера (очереди). Отправитель должен ждать, если очередь заполнена;
ѕ неограниченная емкость очереди сообщений - она имеет бесконечную длину. В данном случае получатель никогда не ждет.
1.2.4 Синхронизация процессов и потоков
Синхронизация может быть выполнена средствами прикладной программы и средствами ОС Более универсальными и эффективными являются средства ОС. В ОС Windows предусмотрены, в частности, cледующие основные объекты синхронизации:
ѕ события ;
ѕ мьютексы ;
ѕ семафоры .
Объектами синхронизации называют специальные системные объекты. которые видны всем потокам. в тога числе и тем, которые принадлежат разным процессам. Объекты могут находиться в двух состояниях: сигнальном и занятом .Смысл «сигнальное состояние» зависит от контекста. Например, поток переходит в сигнальное состояние, когда он заканчивается. Файл переходит в сигнальное состояние, когда операция ввода-вывода для этого файла завершается. Семафор находится в сигнальном состоянии, если его счетчик больше нуля, мьютекс - если он освобожден. Событие находится в сигнальном состоянии, если его флаг установлен (событие произошло)
Объекты синхронизации используются сходным образом. Для создания объекта вызывается функция создания объекта (например. CreateMutex для создания мьютекса). Если объект синхронизации будет использоваться только текущим процессом и его потомками, то при создании можно не указывать имя объекта. Открытие существующего объекта для использования другими процессами выполняется функцией открытия (например, ОpenMutex ). Освобождение объекта осуществляется функцией типа ReleaseMutex. Для других объектов синхронизации используются аналогичные функции.
Следить за состоянием объектов синхронизации можно с помощью специальных системных вызовов. Чаще всего для этого используют функцию WaitForSingleObject (). Функция проверяет, находится та соответствующий объект в сигнальном состоянии. Когда функция при вызове устанавливает, что объект имеет сигнальное состояние, то она тут же возвращает управление вызвавшей программе и сообщает ей об изменении состояния объекта
1.2.5 Критическая секция
Важным понятием синхронизации потоков является понятие «критической секции» программы. Критическая секция -- это часть программы, результат выполнения которой может непредсказуемо меняться, если переменные, относящиеся к этой части программы, изменяются другими потоками в то время, когда выполнение этой части еще не завершено. Критическая секция всегда определяется по отношению к определенным критическим данным, при несогласованном изменении которых могут возникнуть нежелательные эффекты. В предыдущем примере такими критическими данными являлись записи файла базы данных. Во всех потоках, работающих с критическими данными, должна быть определена критическая секция. Заметим, что в разных потоках критическая секция состоит в общем случае из разных последовательностей команд.
Самый простой и в то же время самый неэффективный способ обеспечения взаимного исключения состоит в том, что операционная система позволяет потоку запрещать любые прерывания на время его нахождения в критической секции. Однако этот способ практически не применяется, так как опасно доверять управление системой пользовательскому потоку -- он может надолго занять процессор, а при крахе потока в критической секции крах потерпит вся система, потому что прерывания никогда не будут разрешены.
1.2.6 Взаимоисключения
Объекты-взаимоисключения (мьютексы) позволяют координировать взаимное исключение доступа к разделяемому ресурсу. Сигнальное состояние объекта (т.е. состояние "установлен") соответствует моменту времени, когда объект не принадлежит ни одному потоку и его можно "захватить". И наоборот, состояние "сброшен" (не сигнальное) соответствует моменту, когда какой-либо поток уже владеет этим объектом. Доступ к объекту разрешается, когда поток, владеющий объектом, освободит его.
Для того, чтобы объявить взаимоисключение принадлежащим текущему потоку, надо вызвать одну из ожидающих функций. Поток, которому принадлежит объект, может его "захватывать" повторно сколько угодно раз (это не приведет к самоблокировке), но столько же раз он должен будет его освобождать с помощью функции ReleaseMutex.
1.2.7 События
Объекты-события используются для уведомления ожидающих потоков о наступлении какого-либо события. Различают два вида событий - с ручным и автоматическим сбросом. Ручной сброс осуществляется функцией ResetEvent. События с ручным сбросом используются для уведомления сразу нескольких потоков. При использовании события с автосбросом уведомление получит и продолжит свое выполнение только один ожидающий поток, остальные будут ожидать дальше.
Функция CreateEvent создает объект-событие, SetEvent - устанавливает событие в сигнальное состояние, ResetEvent-сбрасывает событие. Функция PulseEvent устанавливает событие, а после возобновления ожидающих это событие потоков (всех при ручном сбросе и только одного при автоматическом), сбрасывает его. Если ожидающих потоков нет, PulseEvent просто сбрасывает событие.
1.2.8 Семафоры
Объект-семафор - это фактически объект-взаимоисключение со счетчиком. Данный объект позволяет "захватить" себя определенному количеству потоков. После этого "захват" будет невозможен, пока один из ранее "захвативших" семафор потоков не освободит его. Семафоры применяются для ограничения количества потоков, одновременно работающих с ресурсом.
Программа может открыть (создать) семафор с помощью функции OpenSemaphore(), указав его имя. Функция, открывающая семафор, возвращает индекс семафора, который используется для выполнения всех операций над семафором.
С семафором помимо имени связывается некоторое число, которое может находиться в диапазоне от -127 до 127. Это число называется значением семафора.
Кроме того, для каждого семафора имеется счетчик процессов, открывших семафор. Этот счетчик увеличивает свое значение на 1, когда очередная программа открывает семафор функцией OpenSemaphore(), и уменьшает на единицу, когда одна из программ закрывает семафор функцией CloseSemaphore(). Когда счетчик принимает нулевое значение, семафор уничтожается.
Перед использованием критического ресурса, с которым связан семафор, программа должна уменьшить значение семафора, вызвав функцию WaitOnSemaphore(). Если значение семафора равно нулю или больше нуля, программа может использовать ресурс. Если же семафор имеет отрицательное значение, функция WaitOnSemaphore() ожидает семафор в течение указанного ей времени.
После завершения работы с критическим ресурсом программа должна увеличить значение семафора, вызвав функцию SignalSemaphore().
Начальное значение семафора задается при его создании и обычно равно единице.
1.2.9 Сокеты Windows
Windows Sockets API (WSA), название которого было укорочено до Winsock. Это техническая спецификация, которая определяет, как сетевое программное обеспечение Windows будет получать доступ к сетевым сервисам, в том числе, TCP/IP. Он определяет стандартный интерфейс между клиентским приложением (таким как FTP-клиент или веб-браузер) и внешним стеком протоколов TCP/IP. Он основывается на API модели сокетов Беркли, использующейся в BSD для установки соединения между программами.
Есть две версии WinSock
ѕ WinSock 1.1 - поддержка только TCP/IP
ѕ WinSock 2.0 - Поддерка дополнительного программного обеспечения
Спецификация WinSock разделяет функции на три типа:
ѕ функции Беркли;
ѕ информационные функции (получение информации о наименовании доменов, службах, протоколах Internet);
ѕ расширения Windows для функций Беркли;
Все функции могут быть блокирующие и неблокирующие. Обычно блокирующие это функции Беркли. То есть при работе такой функции нельзя выполнять другие функции WinSock.
Давайте расмотрим как производится подключение к серверу. Сначала программа подключается к адресу IP с созданием сокета. Программа будет ждать подключения. Для подключения программа клиент тоже создает сокет и пытается подключиться к сокету сервера. Только он увидит попытку подключения он создаст новый сокет. И этот новый сокет будет использоваться для взаимодействия с клиентом. А тот, к которому была попытка подключения будет ждать следующего. На этой основе производится взаимодействие сервера и многими программами.
Сам сокет может быть создан на основе:
ѕ TCP (transport control protocol) - надежное соединение;
ѕ UDP (user datagram protocol) - ненадежное соединения.
1.3 Разработка и описание алгоритмов работы
1.3.1 Состав и назначение
В состав программного обеспечения, разработанного в соответствии с заданием входят:
ѕ программа, выполняющая функции сервера;
ѕ две программы, выполняющие функции клиентов.
Программа - сервер должна выполнять следующие функции:
ѕ создание сокета;
ѕ получение данных от приложений - клиентов;
ѕ посылать сообщения программам клиентам;
ѕ принимать в асинхронном режиме информацию от программ-клиентов и выводить ее в рабочее окно;
ѕ отключать выбранного клиента.
Программа-клиент должна выполнять следующие функции:
ѕ открытие сокета;
ѕ установка соединение с программой-сервером;
ѕ подготовка и передачи информации программе-серверу;
ѕ принимать и выводить в рабочее окно сообщения от программы-сервера;
ѕ сообщать пользователю об отключении сервера.
1.3.2 Описание программы-сервера
1.3.2.1 Описание переменных
Описание переменных, которые используются в программе дано в таблице 1.3.
Таблица 1.3- Описание переменных и констант программы-сервер
Исходный текст |
Описание |
|
char szBuf[512]; |
Буфер для подготовки данных |
|
DWORD cbWritten; |
Количество записанных данных |
|
static HWND hwndEdit; |
Дескриптор поля редактирования текста |
|
TCHAR mess[2048]; |
Буфер для подготовки сообщений |
|
TCHAR* m_mess = mess; |
Ссылка на буфер подготовки сообщений |
|
#define SERV_PORT 5000 |
Порт сервера |
|
#define WSA_ACCEPT (WM_USER+0) |
Код сообщения на подключение клиента |
|
#define WSA_NETEVENT (WM_USER+1) |
Код сообщения о сетевом событии |
|
WSADATA wsaData; |
Сведения о конкр. реализации интерфейса Windows Sockets |
|
WORD wVersionRequested = MAKEWORD(1, 1); |
Номер требуемой версии Windows Sockets (не ниже) |
|
int err=0; |
Код ошибки |
|
SOCKET srv_socket=INVALID_SOCKET; |
Сокет сервера |
|
int ClientNum = -1; |
Номер текущего клиента |
|
SOCKET sock[2]; |
Сокеты клиентов |
|
SOCKADDR_IN sockaddr[2]; |
Адреса клиентов |
1.3.2.2 Процедура создания сокета
Процедурой выполняются следующие функции:
ѕ проверка на повторность задания сокета;
ѕ создание структуры данных для сокета и получения дескриптора сокета;
ѕ задание типа и значения адреса и номера порта для сокета;
ѕ связывание сокета с адресными данными;
ѕ установка режима прослушивания сети для выявления попыток соединения с сокетом;
ѕ установка режима асинхронного взаимодействия с сокетом.
Схема алгоритма работы процедуры представлена на рисунке 1.1.
Проверка на повторность задания сокета выполняется блоками 2,3 (рисунок 1.1) .
В процедуре создается потоковый сокет и задается структура для хранения адресных данных (блоки 5-7, рисунок 1.1).
Для сокета определяется Интернет семейство адресов. IP адрес устанавливается по умолчанию - обычно это значение адреса локального хоста 127.0.0.1. Номер порта выбран из области свободно используемых значений и равен 5000. С помощью функции htons порядок байтов этого значения преобразуется в сетевой порядок байтов - первым идет старший байт. Эти действия реализуются блоками 9-10 на рисунке 1.1.
Рисунок 1.1 - Схема алгоритма процедуры создание сокета на стороне сервера
Связывание сокета с адресными данными реализуются блоками 11-14 на рисунке 1.1.
Установка режима прослушивания сети для выявления попыток соединения с сокетом реализуются блоками 15-17 на рисунке 1.1.
Установка режима асинхронного взаимодействия с сокетом реализуются блоками 18-21 на рисунке 1.1.
1.3.2.3 Процедура остановки сервера
Схема алгоритма приведена на рисунке 1.2. Остановка выполняется в два действия: сначала отменяется реакция программы на сетевые сообщения от сокета (блок 2, рисунок 1.2), а затем, если сокет был создан, выполняется закрытие сокета (блоки 3 -6, рисунок 1.2).
Рисунок 1.2 - Схема алгоритма остановки сервера
1.3.2.4 Процедура создания соединения
Схема алгоритма процедуры представлена на рисунке 1.3. Предварительно определяется размер структуры SOCKADDR (блок 2, рисунок 1.3), который используется как аргумент при вызове функции accept, которая формирует сокет с новым адресом и возвращает его дескриптор (блок 3, рисунок 1.3). Если сокет был создан, то проверяется наличие в пришедшем запросе на подключение к серверу операции передачи информации или завершения работы клиента. При наличии сокета и перечисленных запросов на выполнение операций функция возвращает значение TRUE, в противном случае FALSE(блоки 4 - 9, рисунок 1.3).
Рисунок 1.3 - Схема алгоритма создания соединения
1.3.2.5 «Оконная» процедура программы-сервера
Схема алгоритма представлена на рисунке 1.4. В схеме алгоритма отражены только действия, связанные с сокетами.
При создании окна приложения-сервера создается также поле ввода, редактирования и отображения текста, подключается библиотека работы с сокетами и о результате подключения выводится сообщение. Эти действия реализованы блоками 4 - 9 на рисунке 1.4, лист1.
Организована обработка сообщений WSA_NETEVENT - о сетевом событии от сокета, WSA_ACCEPT - о запросе на присоединение клиента. Особенность обработки сообщения WM_DESTROY о закрытии окна приложения-сервера является то, что предварительно надо отключиться от библиотеки работы с сокетами. Эти действия реализованы блоками 3,10, 11 - 13 на рисунке 1.4, лист1.
При получении сообщения WM_COMMAND о поступлении команды выполняется ее декодирование и организовывается переключатель для выбора процедуры обработки в зависимости от кода команды. Эти действия реализованы блоками 1 - 8 на рисунке 1.4, лист 2.
Рисунок 1.4, лист 1 - Схема алгоритма «оконной» процедуры программы-сервера
Рисунок 1.4, лист 2.
1.3.3Описание программы-клиента
1.3.3.1Описание переменных
Описание переменных, которые используются в программе дано в таблице 1.2.
Таблица 1.2- Описание переменных программы-клиента
Исходный текст |
Описание |
|
char szBuf[512]; |
Буфер для обменов информацией |
|
DWORD cbWritten; |
Количество байтов, записанных в буфер |
|
static HWND hwndEdit; |
Дескриптор поля редактирования |
|
TCHAR mess[2048]; |
Буфер формирования сообщений на экран |
|
TCHAR* m_mess = mess; |
Ссылка на буфер |
|
#define SERV_PORT 5000 |
Значение номера порта сокета |
|
#define WSA_NETEVENT (WM_USER+1) |
Значение кода сообщения о сетевом событии |
|
WSADATA wsaData; |
сведения о конкретной реализации интерфейса Windows Sockets |
|
WORD wVersionRequested = MAKEWORD( 1, 1 ); |
Номер требуемой версии Windows Sockets |
|
int err=0; |
Код ошибки |
|
SOCKET cln_socket=INVALID_SOCKET; |
Сокет сервера |
|
static PHOSTENT phe; |
Дескриптор компьютера, на котором запущена программа-сервер |
|
SOCKADDR_IN dest_sin; |
Адрес сервера |
|
char szHostName[128] = "localhost"; |
имя хоста |
1.3.3.2Процедура соединения с сервером
Схема алгоритма представлена на рисунке 1.5. Процедурой выполняются следующие функции:
ѕ создание структуры данных для сокета и получения дескриптора сокета;
ѕ определение адреса хоста;
ѕ задание типа и значения адреса и номера порта для сокета;
ѕ установка соединения с сервером;
ѕ установка режима асинхронного взаимодействия с сокетом.
В процедуре создается потоковый сокет и задается структура для хранения адресных данных (блоки 1-5, рисунок 1.5.
С помощью функции gethostbyname по известному имени компьютера в сети определяется его сетевой адрес. Для отладки программ удобно размещать и серверную, и клиентскую программы на одном локальном компьютере. В этом случае задается имя “localhost”. Если серверная и клиентские программы размещаются на разных компьютерах сети, то в качестве имени хоста можно задать сразу IP адрес компьютера-хоста. Эти действия реализованы блоками 6 - 9 на рисунке 1.5 .
Для сокета определяется Интернет семейство адресов. Номер порта выбран из области свободно используемых значений и равен 5000. С помощью функции htons порядок байтов этого значения преобразуется в сетевой порядок байтов - первым идет старший байт. Адрес хоста копируется в структуру данных сокета. Эти действия реализуются блоками 10-11 на рисунке 1.5 .
Соединение сокета с сервером реализуются блоками 12-15 на рисунке 1.5 . Установка режима асинхронного взаимодействия с сокетом реализуются блоками 16-21 на рисунке 1.5 .
Рисунок 1.5 - Схема алгоритма процедуры соединения с сервером
1.3.3.3Процедура посылки информации серверу
Схема алгоритма представлена на рисунке 1.6. С помощью системной функции SendMessage определяется длина блока информации для сервера и выполняется пересылка этого блока в буфер. С помощью функции send выполняется пересылка информации серверу и в зависимости от результата выполнения функции выводится сообщение на экран. Эти действия реализуются блоками 1-8 на рисунке 1.6.
Рисунок 1.6 - Схема алгоритма процедуры посылки информации серверу
1.3.3.4«Оконная» процедура программы-клиента
Схема алгоритма представлена на рисунке 1.7. В схеме алгоритма отражены только действия, связанные с сокетами.
При создании окна приложения-клиента создается также поле ввода, редактирования и отображения текста, подключается библиотека работы с сокетами и о результате подключения выводится сообщение. Эти действия реализованы блоками 3 - 7 на рисунке 1.7.
Организована обработка сообщений WSA_NETEVENT - о сетевом событии от сокета. Анализируется принятый код события. Если это код чтения данных, то вызывается функция recv приема информации из сокета в буфер. Если это код завершения работы сервера, то выводится сообщение на экран. Эти действия реализованы блоками 10 - 14 на рисунке 1.7.
При обработке сообщения WM_DESTROY о закрытии окна приложения-клиента является то, что предварительно надо отключиться от библиотеки работы с сокетами. Эти действия реализованы блоками 15 - 17 на рисунке 1.7. При получении сообщения WM_COMMAND о поступлении команды выполняется ее декодирование и организовывается переключатель для выбора процедуры обработки в зависимости от кода команды. Эти действия реализованы блоками 18 - 22 на рисунке 1.7.
Рисунок 1.7 - Схема алгоритма «оконной» процедуры программы-клиента
1.4 Результаты применения программы
Разработка и отладка программы выполнялась в среде Microsoft Visual Studio. Разработано одно приложение-сервер и два приложения клиента, которые подтвердили свою работоспособность. Копии экранов работающих приложений приведены на рисунке 1.8.
Рисунок 1.8 - Копии экранов серверного и клиентских приложений
ВЫВОДЫ
В ходе выполнения курсовой роботы получены положительные результаты. Разработано и отлажено 3 приложения. Приложение - сервер выполняет такие функции:
ѕ создание сокетов;
ѕ получение информации от приложений - клиентов;
ѕ вывод на экран полученных результатов.
Приложение - клиент 1 выполняет такие функции:
ѕ открытие сокета;
ѕ установка соединения с сервером;
ѕ подготовка и передача такой системной информации:
a) системные цвета 2-х элементов окна приложения;
b) код раскладки клавиатуры.
Приложение - клиент 1 выполняет такие функции:
ѕ открытие сокета;
ѕ установка соединения с сервером;
ѕ подготовка и передача такой системной информации:
a)идентификатор текущего процесса;
b)дескриптор текущего процесса.
ПЕРЕЧЕНЬ ССЫЛОК
1. http://www.rsdn.ru/article/baseserv/mt.xml
2. http://vunivere.ru/work11218
3. Методические указания к курсовой работе по дисциплине "Системное программное обеспечение" (для студентов дневной и заочной формы обучения, обучающихся по направлению 6.050102 «Компьютерная инженерия» / Сост.: Брежнев А.М. - Северодонецк: 2013. - 71 с.
4. http://frolov-lib.ru/books/bsp/v23/ch5_3.html
5. http://gendocs.ru/v31765/?cc=32
6. http://life-prog.ru/view_linux.php?id=23
ПРИЛОЖЕНИЯ
Приложение А
Распечатка программы сервера
1. // Сервер.cpp: определяет точку входа для приложения.
2. //
3. #include "stdafx.h"
4. #include "Сервер.h"
5. #include <windows.h>
6. #include <windowsx.h>
7. #include <winsock.h>
8. #include <commctrl.h>
9. #include <stdlib.h>
10. #include <stdio.h>
11. char szBuf[512];
12. DWORD cbWritten;
13. static HWND hwndEdit;
14. TCHAR mess[2048];
15. TCHAR* m_mess = mess;
16. #define SERV_PORT 5000// Порт сервера
17. #define WSA_ACCEPT (WM_USER+0)
18. #define WSA_NETEVENT (WM_USER+1)
19. #define MAX_LOADSTRING 100
20. WSADATA wsaData; //сведения о конкр. реализации интерфейса Windows Sockets
21. WORD wVersionRequested = MAKEWORD(1, 1); //Номер требуемой версии Windows Sockets
22. int err=0;
23. SOCKET srv_socket=INVALID_SOCKET; // Сокет сервера
24. int ClientNum = -1;// Номер последнего клиента
25. SOCKET sock[2];// Сокеты клиентов
26. SOCKADDR_IN sockaddr[2];// Адреса клиентов
27. // Глобальные переменные:
28. HINSTANCE hInst;// текущий экземпляр
29. TCHAR szTitle[MAX_LOADSTRING]; // Текст строки заголовка
30. TCHAR szWindowClass[MAX_LOADSTRING];// имя класса главного окна
31. HWND hWindow;
32. // Отправить объявления функций, включенных в этот модуль кода:
33. ATOMMyRegisterClass(HINSTANCE hInstance);
34. BOOLInitInstance(HINSTANCE, int);
35. LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);
36. INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);
37. int APIENTRY _tWinMain(HINSTANCE hInstance,
38. HINSTANCE hPrevInstance,
39. LPTSTR lpCmdLine,
40. int nCmdShow)
41. {
42. UNREFERENCED_PARAMETER(hPrevInstance);
43. UNREFERENCED_PARAMETER(lpCmdLine);
44. // TODO: разместите код здесь.
45. MSG msg;
46. HACCEL hAccelTable;
47. // Инициализация глобальных строк
48. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
49. LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);
50. MyRegisterClass(hInstance);
51. // Выполнить инициализацию приложения:
52. if (!InitInstance (hInstance, nCmdShow))
53. {
54. return FALSE;
55. }
56. hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));
57. // Цикл основного сообщения:
58. while (GetMessage(&msg, NULL, 0, 0))
59. {
60. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
61. {
62. TranslateMessage(&msg);
63. DispatchMessage(&msg);
64. }
65. }
66. return (int) msg.wParam;
67. }
68. //
69. // ФУНКЦИЯ: MyRegisterClass()
70. //
71. // НАЗНАЧЕНИЕ: регистрирует класс окна.
72. //
73. // КОММЕНТАРИИ:
74. //
75. // Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
76. // был совместим с системами Win32, не имеющими функции RegisterClassEx'
77. // которая была добавлена в Windows 95. Вызов этой функции важен для того,
78. // чтобы приложение получило "качественные" мелкие значки и установило связь
79. // с ними.
80. //
81. ATOM MyRegisterClass(HINSTANCE hInstance)
82. {
83. WNDCLASSEX wcex;
84. wcex.cbSize = sizeof(WNDCLASSEX);
85. wcex.style= CS_HREDRAW | CS_VREDRAW;
86. wcex.lpfnWndProc= WndProc;
87. wcex.cbClsExtra= 0;
88. wcex.cbWndExtra= 0;
89. wcex.hInstance= hInstance;
90. wcex.hIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));
91. wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
92. wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
93. wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY);
94. wcex.lpszClassName= szWindowClass;
95. wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
96. return RegisterClassEx(&wcex);
97. }
98. //
99. // ФУНКЦИЯ: InitInstance(HINSTANCE, int)
100. //
101. // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
102. //
103. // КОММЕНТАРИИ:
104. //
105. В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
106. // создается и выводится на экран главное окно программы.
107. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
108. {
109. HWND hWnd;
110. hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
111. hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
112. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
113. if (!hWnd)
114. {
115. return FALSE;
116. }
117. hWindow=hWnd;
118. ShowWindow(hWnd, nCmdShow);
119. UpdateWindow(hWnd);
120. return TRUE;
121. }
122. void ServerStart( HWND hWnd )
123. {
124. if(srv_socket != INVALID_SOCKET )
125. {
126. MessageBox( hWnd, "Socket уже есть", "Info", MB_OK | MB_ICONINFORMATION );
127. return;
128. }
129. // создаем сокет сервера для работы с потоком данных
130. srv_socket = socket( AF_INET, SOCK_STREAM, 0 );
131. if( srv_socket == INVALID_SOCKET )
132. {
133. MessageBox( hWnd, "Ошибка создания сокета!!!", "Error", MB_OK | MB_ICONERROR );
134. return;
135. }
136. // Устанавливаем адрес IP и номер порта
137. SOCKADDR_IN srv_address;
138. srv_address.sin_family = AF_INET;
139. srv_address.sin_port = htons( SERV_PORT );
140. srv_address.sin_addr.s_addr = INADDR_ANY; // исп. адрес по умолчанию (т.е. любой)
141. // Связываем адрес IP с сокетом
142. if(SOCKET_ERROR ==bind(srv_socket,(LPSOCKADDR) &srv_address, sizeof(srv_address) ) )
143. {
144. closesocket( srv_socket );
145. MessageBox( hWnd, "Ошибка связывания с портом", "Error", MB_OK | MB_ICONSTOP );
146. return;
147. }
148. // ожидаем установки связи
149. if( listen( srv_socket, 4 ) == SOCKET_ERROR )
150. {
151. closesocket( srv_socket );
152. MessageBox( hWnd, "Ошибка ожидания установки связи","Error", MB_OK );
153. return;
154. }
155. // при попытке соединения главное окно получит сообщение WSA_ACCEPT
156. int rc = WSAAsyncSelect( srv_socket, hWnd, WSA_ACCEPT, FD_ACCEPT );
157. if( rc )
158. {
159. closesocket( srv_socket );
160. MessageBox( hWnd, "WSAAsyncSelect error","Error", MB_OK );
161. return;
162. }
163. // Выводим сообщение о запуске сервера
164. SendMessage( hwndEdit, WM_SETTEXT, 0, ( LPARAM ) "Сервер запущен" );
165. }
166. void ServerStop( HWND hWnd )
167. {
168. // отменяем приход сообщений в главную функцию окна при возникновении
169. // любых событий, связанных с системой Windows Sockets
170. WSAAsyncSelect( srv_socket, hWnd, 0, 0 );
171. if( srv_socket != INVALID_SOCKET ) // если сокет был создан, закрываем его
172. {
173. closesocket( srv_socket );
174. srv_socket = INVALID_SOCKET;
175. }
176. // выводим сообщение об останове сервера
177. SendMessage( hwndEdit, WM_SETTEXT, 0, (LPARAM) "Сервер остановлен" );
178. }
179. BOOL AcceptClient(int j)// присоединить клиента
180. {
181. int sockaddr_len = sizeof( sockaddr[j] );
182. sock[j]=accept( srv_socket,(LPSOCKADDR)&sockaddr[j],(int FAR*)&sockaddr_len );
183. if( sock[j] != INVALID_SOCKET )
184. if(!WSAAsyncSelect( sock[j],hWindow,WSA_NETEVENT, FD_READ | FD_CLOSE ))
185. return TRUE;
186. closesocket( sock[j] );
187. return FALSE;
188. }
189. void DisconnectClient(int j)// отключить клиента
190. {
191. WSAAsyncSelect( sock[j], hWindow, 0, 0 );
192. closesocket(sock[j]);
193. }
194. void WndProc_OnWSAAccept( HWND hWnd, LPARAM lParam )
195. {
196. // при ошибке отменяем поступление сообщений в главное окно приложения
197. if( WSAGETSELECTERROR( lParam ) ){
198. MessageBox( hWnd, "accept error", "Error", MB_OK );
199. WSAAsyncSelect( srv_socket, hWnd, 0, 0 );
200. return;
201. }
202. if( ClientNum == 1){
203. MessageBox( hWnd,"число клиентов >2\r\n", "Соединение недопустимо!", MB_OK );
204. return;
205. }
206. ClientNum++;
207. if(!AcceptClient(ClientNum) ){
208. MessageBox( hWnd, "Ошибка соед с клиентом", "Error", MB_OK );
209. return;
210. }
211. // добавляем клиента
212. sprintf(szBuf, "Добавлен клиент %i\r\nАдрес: IP=%s Port=%u\r\n \0", ClientNum+1,
213. inet_ntoa(sockaddr[ClientNum].sin_addr), htons(sockaddr[ClientNum].sin_port));
214. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
215. }
216. void WndProc_OnWSANetEvent( HWND hWnd, WPARAM wParam, LPARAM lParam )
217. {
218. char szTemp[256], szMess[256];
219. int Number;
220. // узнаем от какого клиента пришло сообщение, => Number
221. if( sock[0]==(SOCKET) wParam ) Number=0;
222. else if( sock[1]==(SOCKET) wParam ) Number=1;
223. // если на сокете выполняется передача данных, принимаем и отображаем их
224. if( WSAGETSELECTEVENT( lParam ) == FD_READ )
225. {
226. int rc = recv( (SOCKET) wParam, szTemp, 256, 0 );
227. if(rc){
228. szTemp[rc]='\0';
229. sprintf( m_mess, "%s \r\n Данные от Клиента %i:\r\n%s", m_mess, Number+1,szTemp );
230. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
231. }
232. }
233. // если соединение завершено, выводим сообщение об этом
234. if( WSAGETSELECTEVENT( lParam ) == FD_CLOSE )
235. {
236. WSAAsyncSelect( sock[Number], hWindow, 0, 0 );
237. closesocket(sock[Number]);
238. sprintf( szTemp, "Клиент %i завершил работу", Number+1 );
239. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szTemp);
240. }
241. }
242. void SendToClient(int j)
243. {
244. if(j>ClientNum) return;
245. cbWritten = SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
246. SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) cbWritten, (LPARAM) szBuf);
247. szBuf[cbWritten]='\0';
248. if( send(sock[j],szBuf,lstrlen(szBuf),0) != SOCKET_ERROR)
249. {
250. sprintf(szBuf, "Данные отосланы клиенту %d\r\n %s",j+1,szBuf);
251. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
252. }
253. else
254. SendMessage(hwndEdit,WM_SETTEXT, 0, (LPARAM)"Ошибка отправки сообщения \r\n");
255. }
256. void ClientOff(HWND hWnd, int j)
257. {
258. if(j>ClientNum) return;
259. sprintf( szBuf, "Отключить Клиента %i?", j+1 );
260. if( IDYES == MessageBox( hWnd, szBuf, "Question", MB_YESNO | MB_ICONQUESTION ) )
261. DisconnectClient(j);
262. ClientNum--;
263. }
264. //
265. // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
266. //
267. // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне.
268. //
269. // WM_COMMAND- обработка меню приложения
270. // WM_PAINT-Закрасить главное окно
271. // WM_DESTROY - ввести сообщение о выходе и вернуться.
272. //
273. //
274. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
275. {
276. int wmId, wmEvent;
277. PAINTSTRUCT ps;
278. HDC hdc;
279. switch (message)
280. {
281. case WM_CREATE:
282. hwndEdit = CreateWindow( // Создаем доч.окно для вывода данных от процессов
283. TEXT("EDIT"), NULL,
284. WS_CHILD | WS_VISIBLE | WS_VSCROLL |
285. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
286. 0, 0, 400, 200, hWnd, NULL, hInst, NULL);
287. err = WSAStartup( wVersionRequested, &wsaData );
288. if( err ){
289. MessageBox( hWnd, "WSAStartup Error","ERROR", MB_OK | MB_ICONSTOP );
290. return FALSE;
291. }
292. sprintf(m_mess, "Используется %s \r\nСтатус: %s\r\n",
293. wsaData.szDescription, wsaData.szSystemStatus);
294. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
295. break;
296. case WM_COMMAND:
297. wmId = LOWORD(wParam);
298. wmEvent = HIWORD(wParam);
299. // Разобрать выбор в меню:
300. switch (wmId)
301. {
302. case ID_32771:
303. ServerStart( hWnd );
304. break;
305. case ID_32772:
306. ServerStop( hWnd );
307. break;
308. case ID_32773:
309. SendToClient(0);
310. break;
311. case ID_32774:
312. SendToClient(1);
313. break;
314. case ID_32775:
315. ClientOff(hWnd, 0);
316. break;
317. case ID_32776:
318. ClientOff(hWnd, 1);
319. break;
320. case IDM_ABOUT:
321. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
322. break;
323. case IDM_EXIT:
324. DestroyWindow(hWnd);
325. break;
326. default:
327. return DefWindowProc(hWnd, message, wParam, lParam);
328. }
329. break;
330. case WM_PAINT:
331. hdc = BeginPaint(hWnd, &ps);
332. // TODO: добавьте любой код отрисовки...
333. EndPaint(hWnd, &ps);
334. break;
335. case WM_DESTROY:
336. WSACleanup( );
337. PostQuitMessage(0);
338. break;
339. case WSA_ACCEPT:
340. WndProc_OnWSAAccept( hWnd, lParam );
341. break;
342. case WSA_NETEVENT:
343. WndProc_OnWSANetEvent( hWnd, wParam, lParam );
344. break;
345. default:
346. return DefWindowProc(hWnd, message, wParam, lParam);
347. }
348. return 0;
349. }
350. // Обработчик сообщений для окна "О программе".
351. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
352. {
353. UNREFERENCED_PARAMETER(lParam);
354. switch (message)
355. {
356. case WM_INITDIALOG:
357. return (INT_PTR)TRUE;
358. case WM_COMMAND:
359. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
360. {
361. EndDialog(hDlg, LOWORD(wParam));
362. return (INT_PTR)TRUE;
363. }
364. break;
365. }
366. return (INT_PTR)FALSE;
367. }
368.
Приложение Б
Распечатка программы клиента 1
369. // Клиент1.cpp: определяет точку входа для приложения.
370. //
371. #include "stdafx.h"
372. #include "Клиент1.h"
373. #include <winsock.h>
374. #include <process.h>
375. #include <stdio.h>
376. #include <windows.h>
377. #include <tchar.h>
378. #include <string.h>
379. #include <iostream>
380. char szBuf[512];
381. DWORD cbWritten;
382. int flag = 0;
383. static HWND hwndEdit;
384. TCHAR mess[2048];
385. TCHAR* m_mess = mess;
386. int wmId, wmEvent;
387. PAINTSTRUCT ps;
388. HDC hdc;
389. HWND hwnd;
390. RECT rt;
391. #define SERV_PORT 5000// Порт сервера
392. #define WSA_NETEVENT (WM_USER+1)
393. WSADATA wsaData; //сведения о конкретной реализации интерфейса Windows Sockets
394. WORD wVersionRequested = MAKEWORD( 1, 1 ); //Номер требуемой версии Windows Sockets
395. int err=0;
396. SOCKET cln_socket=INVALID_SOCKET; // Сокет сервера
397. static PHOSTENT phe;
398. SOCKADDR_IN dest_sin; // Адрес сервера
399. char szHostName[128] = "localhost"; //имя хоста
400. #define MAX_LOADSTRING 100
401. // Глобальные переменные:
402. HINSTANCE hInst;// текущий экземпляр
403. TCHAR szTitle[MAX_LOADSTRING];// Текст строки заголовка
404. TCHAR szWindowClass[MAX_LOADSTRING];// имя класса главного окна
405. // Отправить объявления функций, включенных в этот модуль кода:
406. ATOMMyRegisterClass(HINSTANCE hInstance);
407. BOOLInitInstance(HINSTANCE, int);
408. LRESULT CALLBACKWndProc(HWND, UINT, WPARAM, LPARAM);
409. INT_PTR CALLBACKAbout(HWND, UINT, WPARAM, LPARAM);
410. int APIENTRY _tWinMain(HINSTANCE hInstance,
411. HINSTANCE hPrevInstance,
412. LPTSTR lpCmdLine,
413. int nCmdShow)
414. {
415. UNREFERENCED_PARAMETER(hPrevInstance);
416. UNREFERENCED_PARAMETER(lpCmdLine);
417. // TODO: разместите код здесь.
418. MSG msg;
419. HACCEL hAccelTable;
420. // Инициализация глобальных строк
421. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
422. LoadString(hInstance, IDC_MY1, szWindowClass, MAX_LOADSTRING);
423. MyRegisterClass(hInstance);
424. // Выполнить инициализацию приложения:
425. if (!InitInstance (hInstance, nCmdShow))
426. {
427. return FALSE;
428. }
429. hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY1));
430. // Цикл основного сообщения:
431. while (GetMessage(&msg, NULL, 0, 0))
432. {
433. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
434. {
435. TranslateMessage(&msg);
436. DispatchMessage(&msg);
437. }
438. }
439. return (int) msg.wParam;
440. }
441. //
442. // ФУНКЦИЯ: MyRegisterClass()
443. //
444. // НАЗНАЧЕНИЕ: регистрирует класс окна.
445. //
446. // КОММЕНТАРИИ:
447. //
448. // Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
449. // был совместим с системами Win32, не имеющими функции RegisterClassEx'
450. // которая была добавлена в Windows 95. Вызов этой функции важен для того,
451. // чтобы приложение получило "качественные" мелкие значки и установило связь
452. // с ними.
453. //
454. ATOM MyRegisterClass(HINSTANCE hInstance)
455. {
456. WNDCLASSEX wcex;
457. wcex.cbSize = sizeof(WNDCLASSEX);
458. wcex.style= CS_HREDRAW | CS_VREDRAW;
459. wcex.lpfnWndProc= WndProc;
460. wcex.cbClsExtra= 0;
461. wcex.cbWndExtra= 0;
462. wcex.hInstance= hInstance;
463. wcex.hIcon= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY1));
464. wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
465. wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
466. wcex.lpszMenuName= MAKEINTRESOURCE(IDC_MY1);
467. wcex.lpszClassName= szWindowClass;
468. wcex.hIconSm= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
469. return RegisterClassEx(&wcex);
470. }
471. //
472. // ФУНКЦИЯ: InitInstance(HINSTANCE, int)
473. //
474. // НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
475. //
476. // КОММЕНТАРИИ:
477. //
478. //В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
479. // создается и выводится на экран главное окно программы.
480. //
481. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
482. {
483. HWND hWnd;
484. hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
485.
486. hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
487. CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
488.
489. if (!hWnd)
490. {
491. return FALSE;
492. }
493.
494. ShowWindow(hWnd, nCmdShow);
495. UpdateWindow(hWnd);
496.
497. return TRUE;
498. }
499. void Task1()
500. {
501. HKL layot = GetKeyboardLayout(0);
502. DWORD wn = GetSysColor(COLOR_WINDOW);
503. DWORD frame = GetSysColor(COLOR_WINDOWFRAME);
504. char str[256];
505. sprintf(str, "Код раскладки клавиатуры: %d\r\n",layot );
506. strcat_s(szBuf, str);
507. sprintf(str, "Цвет фона окна: %d\r\n",wn );
508. strcat_s(szBuf, str);
509. sprintf(str, "Цвет фона рамки: %d\r\n",frame);
510. strcat_s(szBuf, str);
511. }
512. BOOL SetConnection( HWND hWnd )
513. {
514. cln_socket = socket( AF_INET, SOCK_STREAM, 0 ); // создаем сокет
515. if ( cln_socket == INVALID_SOCKET )
516. {
517. MessageBox( hWnd, "Socket error", "Error", MB_OK | MB_ICONSTOP );
518. return FALSE;
519. }
520. phe = gethostbyname( szHostName ); // Определяем адрес узла
521. if( phe == NULL )
522. {
523. closesocket( cln_socket );
524. MessageBox( hWnd, "Адрес хоста не определен", "Error", MB_OK | MB_ICONSTOP );
525. return FALSE;
526. }
527. dest_sin.sin_family = AF_INET;// Задаем тип адреса
528. dest_sin.sin_port = htons( SERV_PORT );// Устанавливаем номер порта
529. memcpy( (char FAR*) &(dest_sin.sin_addr), phe->h_addr, phe->h_length );// Копируем адрес узла
530. // Устанавливаем соединение
531. if( connect( cln_socket, (PSOCKADDR) &dest_sin, sizeof(dest_sin) ) == SOCKET_ERROR )
532. {
533. closesocket( cln_socket );
534. MessageBox( hWnd, "Ошибка соединения", "Error", MB_OK | MB_ICONSTOP );
535. return FALSE;
536. }
537. // при попытке соединения главное окно получит сообщение WSA_ACCEPT
538. if( WSAAsyncSelect( cln_socket, hWnd, WSA_NETEVENT, FD_READ | FD_CLOSE ) )
539. {
540. MessageBox( hWnd, "WSAAsyncSelect error", "Error", MB_OK );
541. return FALSE;
542. }
543. // Выводим сообщение об установке соединения с узлом
544. SendMessage( hwndEdit, WM_SETTEXT, 0, ( LPARAM ) "Связь установлена!" );
545. return TRUE;
546. }
547.
548. void SendMsg( HWND hWnd )
549. {
550. cbWritten = SendMessage(hwndEdit,WM_GETTEXTLENGTH,0,0);
551. SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) cbWritten, (LPARAM) szBuf);
552. if( send(cln_socket,szBuf,lstrlen(szBuf),0) != SOCKET_ERROR)
553. {
554. sprintf(m_mess, "\r\n Данные отосланы серверу \r\n %s",szBuf);
555. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
556. }
557. else
558. {
559. sprintf(m_mess, "%s \r\n Ошибка отправки сообщения \r\n ",m_mess);
560. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
561. }
562. }
563. // ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
564. //
565. // НАЗНАЧЕНИЕ: обрабатывает сообщения в главном окне.
566. //
567. // WM_COMMAND- обработка меню приложения
568. // WM_PAINT-Закрасить главное окно
569. // WM_DESTROY - ввести сообщение о выходе и вернуться.
570. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
571. {
572. int wmId, wmEvent;
573. PAINTSTRUCT ps;
574. HDC hdc;
575. switch (message)
576. {
577. case WM_CREATE:
578. hwndEdit = CreateWindow( // Создаем доч.окно для вывода данных от процессов
579. TEXT("EDIT"), NULL,
580. WS_CHILD | WS_VISIBLE | WS_VSCROLL |
581. ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
582. 0, 0, 400, 200, hWnd, NULL, hInst, NULL);
583. err = WSAStartup( wVersionRequested, &wsaData );
584. if( err ){
585. MessageBox( hWnd, "WSAStartup Error","ERROR", MB_OK | MB_ICONSTOP );
586. return FALSE;
587. }
588. sprintf(m_mess, "Используется %s \r\nСтатус: %s\r\n ",
589. wsaData.szDescription, wsaData.szSystemStatus);
590. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
591. break;
592. case WM_COMMAND:
593. wmId = LOWORD(wParam);
594. wmEvent = HIWORD(wParam);
595. // Разобрать выбор в меню:
596. switch (wmId)
597. {
598. case ID_32771:
599. SetConnection( hWnd );
600. break;
601. case ID_32772:
602. Task1();
603. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)szBuf);
604. break;
605. case ID_32773:
606. SendMsg( hWnd );
607. break;
608. case WSA_NETEVENT:
609. // если на сокете выполняется передача данных, принимаем и отображаем их
610. if( WSAGETSELECTEVENT( lParam ) == FD_READ )
611. {
612. int rc = recv( cln_socket, szBuf, sizeof(szBuf), 0 );
613. if( rc )
614. {
615. szBuf[rc]='\0';
616. sprintf(m_mess, "%s \r\n Данные от сервера: %s\r\n ",m_mess ,szBuf);
617. SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM)m_mess);
618. }
619. }
620. // если соединение завершено, выводим сообщение об этом
621. if( WSAGETSELECTEVENT( lParam ) == FD_CLOSE )
622. MessageBox( hWnd, "Сервер закрыт", "Server", MB_OK );
623. break;
624. case IDM_ABOUT:
625. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
626. break;
627. case IDM_EXIT:
628. DestroyWindow(hWnd);
629. break;
630. default:
631. return DefWindowProc(hWnd, message, wParam, lParam);
632. }
633. break;
634. case WM_PAINT:
635. hdc = BeginPaint(hWnd, &ps);
636. // TODO: добавьте любой код отрисовки...
637. EndPaint(hWnd, &ps);
638. break;
639. case WM_DESTROY:
640. PostQuitMessage(0);
641. break;
642. default:
643. return DefWindowProc(hWnd, message, wParam, lParam);
644. }
645. return 0;
646. }
647. // Обработчик сообщений для окна "О программе".
648. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
649. {
650. UNREFERENCED_PARAMETER(lParam);
651. switch (message)
652. {
653. case WM_INITDIALOG:
654. return (INT_PTR)TRUE;
655. case WM_COMMAND:
656. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
657. {
658. EndDialog(hDlg, LOWORD(wParam));
659. return (INT_PTR)TRUE;
660. }
661. break;
662. }
663. return (INT_PTR)FALSE;
Подобные документы
Разработка приложений на платформе Win32 для исследования взаимодействия между процессами через отображение файла в память. Модель приложений "клиент - сервер". Описание алгоритма работы программы-клиента и программы-сервера. Результаты работы приложений.
курсовая работа [869,3 K], добавлен 18.05.2014Анализ архитектуры информационной системы, в структуру которой входят системы файл-сервер и клиент-сервер. Сравнение языков запросов SQL и QBE. Принципы разработки приложений архитектуры клиент-сервер при помощи структурированного языка запросов SQL.
курсовая работа [88,9 K], добавлен 11.04.2010Основные вехи на пути развития систем программирования. Microsoft Access - первая СУБД для персональных компьютеров, созданная для работы в среде Windows. Перенос файл-серверных приложений в среду клиент-сервер. Использование ActiveX Data Objects.
презентация [662,2 K], добавлен 11.04.2013Варианты топологии одноранговой вычислительной сети, принцип работы распределенных пиринговых сетей. Использование в крупных сетях модели "клиент-сервер". Характеристика операционных систем с сетевыми функциями, многопроцессорная обработка информации.
творческая работа [51,8 K], добавлен 26.12.2011Обзор существующего программного обеспечения. Структура и отличительные особенности формата MP3. Сокеты TCP/IP, клиент-сервер. Язык программирования Visual Basic.net в среде разработки Visual Studio 2008. Разработка приложения "MP3_Catalogizator".
дипломная работа [2,1 M], добавлен 09.02.2015Архитектура "клиент-сервер". Системный анализ базы данных "Газета объявлений", ее инфологическое и физическое проектирование. Программирование на стороне SQL-сервера. Разработка клиентской части в Borland C++ Builder 6.0 и с помощью Web-технологий.
курсовая работа [1,3 M], добавлен 07.07.2013Методика и основные этапы разработки системы тестирования для оценки уровня знаний студентов с применением технологии "Клиент-сервер". Проектирование клиентской, серверной части данной системы тестирования, порядок составления финальных отчетов.
дипломная работа [587,6 K], добавлен 08.11.2010Характеристика разновидностей программной реализации чатов. Разработка программы клиент-серверного чата с возможность общения в локальной сети нескольких человек одновременно. Протокол взаимодействия клиента и сервера. Порядок работы с программой.
курсовая работа [530,7 K], добавлен 25.04.2015Устройство веб-приложений, преимущества их построения. Характеристика технологий веб-программирования, используемых на стороне сервера и на стороне клиента. Формирование и обработка запросов, создание интерактивного и независимого от браузера интерфейса.
контрольная работа [76,4 K], добавлен 08.07.2014Описание предметной области и разработка электронного учебника на основе архитектуры "клиент – сервер". Тестирование программы менеджера и создание интерфейса главного меню. Вход в программу в качестве пользователя и обеспечение перехода к данным лекций.
курсовая работа [1,5 M], добавлен 26.02.2015