close

Вход

Забыли?

вход по аккаунту

?

KursAGOTOV

код для вставкиСкачать
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ
Федеральное государственное бюджетное образовательное
учреждение высшего профессионального образования
«Пензенский государственный университет»
(ФГБОУ ВПО «Пензенский государственный университет»)
______________________________________________________________________
Кафедра «Вычислительная техника»
Пояснительная записка
к курсовому проекту по дисциплине
«Сети ЭВМ и телекоммуникации»
на тему:
“Разработка системы передачи файла в локальной вычислительной сети”
Вариант 1.
Выполнил студент гр.09ВП2
Башев А. С.
Руководитель работы
Гурин Е.И.
Работа защищена «___» _____ 2012 г.
Оценка _______________
Пенза 2012
РЕФЕРАТ
Отчёт содержит 55 листов, 20 рисунков, 3 таблицы, 5 использованных
источников
Ключевые
слова:
КЛИЕНТ,
СЕРВЕР,
СОКЕТ,
ФАЙЛ,
КЛАСС,
ДАННЫЕ,
ПЕРЕДАЧА, ПРИЁМ.
Объект разработки – система программ, осуществляющих взаимодействие
посредством локальной вычислительной сети.
Цель работы — исследование механизмов внутрисетевого взаимодействия
программных систем, посредством разработки клиент-серверного приложения.
Технология разработки – объектно-ориентированное программирование.
Результаты работы – созданы компоненты программного обеспечения, то
есть продукт, отвечающий требованиям задания на курсовое проектирование.
Приобретены соответствующие навыки.
Изм Лист № докум.
.Разраб. Башев А. С.
Пров.
Гурин Е. И.
Н. контр.
Утв.
Подп.
Дата
ПГУ 230105–7КП092.01 ПЗ
«Разработка системы передачи
файла в локальной
вычислительной сети»
Лит.
Лист
3
Группа 09ВП2
Листов
Листов
55
4
Содержание
Введение ............................................................................................................................... 5
1.
Разработка клиент-серверного приложения, где сервер рассылает заранее
известный файл множеству клиентов по запросу ............................................................ 6
1.1. Анализ предметной области .................................................................................. 6
1.2. Анализ требований к программным средствам ................................................... 7
1.3. Описание реализуемых алгоритмов ..................................................................... 9
1.4. Анализ требований к интерфейсу пользователя. .............................................. 10
2.
Проектирование ....................................................................................................... 10
2.1. Проектирование программной модели ............................................................... 10
2.2. Проектирование интерфейса пользователя........................................................ 11
2.3. Описание работы системы ................................................................................... 13
2.4. Описание работы программы .............................................................................. 15
2.5. Реализация ............................................................................................................. 16
2.5.1. Реализация серверного приложения ............................................................ 16
2.5.2. Реализация клиентского приложения .......................................................... 18
2.6. Руководство оператора ......................................................................................... 19
2.6.1. Серверное приложение.................................................................................. 19
2.6.2. Клиентское приложение ................................................................................ 20
3.
Методика тестрования программы ........................................................................ 21
Заключение......................................................................................................................... 25
Список использованных источников .............................................................................. 26
ПРИЛОЖЕНИЕ А . Схема взаимодействия программ …………………………… ... 27
ПРИЛОЖЕНИЕ Б. Схема работы системы ……………………………….…………. 29
ПРИЛОЖЕНИЕ В. Схема работы программ ………………………………………… 31
ПРИЛОЖЕНИЕ Г. Результаты тестирования ………………………………………... 34
ПРИЛОЖЕНИЕ Д. Код программы …..………………………………………………. 43
5
Введение
В связи с постоянным ростом и развитием компьютерных вычислительных
сетей
сетевое
программирование
является
основой
множества
сложный
вычислительных систем и занимает большую роль в разработке любых приложений.
Компьютерные сети основаны на принципе клиент-сервер, в соответствии с
которым действия по обработке информации, необходимые для выполнения
конкретной задачи, разделены между компьютерами, выполняющими функции
клиентов или серверов. Сервер – это ЭВМ, обеспечивающая доступ к информации
другим компьютерам в тот момент, когда им это потребуется или обрабатывающая
поступающие от них запросы. Клиент – ЭВМ, запрашивающий информацию у
сервера посредством запроса к нему через определенный интерфейс. Оба термина
применяются как к физическим устройствам, так и к программному обеспечению.
Для обеспечения взаимодействия процессов, запущенных на разных машинах,
находящихся в единой сети, используется механизм сокетов. Задачей данного
курсового проекта является исследование данного механизма, посредством создания
клиент-серверного приложения.
В качестве языка разработки выбран язык программирования C++. Поскольку
целевой
операционной
системой
программный интерфейс WinSock.
является
Windows
XP,
то
используется
6
1. Разработка клиент-серверного приложения, где сервер по
запросам множеcтва клиентов ищет строку в файле.
1.1.
Анализ предметной области
Процесс работы клиент-серверного приложения должен заключаться в
циклическом выполнении следующих этапов:
1. Программа «клиент» передаёт программе «сервер»
запрос с именем
файла и искомой строкой.
2. Программа «сервер» проверяет наличие файла на своём компьютере,
ищет искомую строку в файле и передает результат поиска на «клиент».
3. Программа «клиент» принимает результат запроса и выводит сообщение
о результате на экран.
При этом программа «сервер» должна поддерживать множество соединений с
программами «клиент».
Поскольку программы «клиент» и «сервер» могут находиться на разных
машинах на значительном расстоянии друг от друга, то следует организовать
вышеописанный обмен данными между ними с помощью сокетов. Сокеты
поддерживают многие стандартные сетевые протоколы (зависищие от реализации
сокета) и предоставляют унифицированный интерфейс для работы с ними.
Сокет (socket) – название программного интерфейса для обеспечения обмена
данными между процессами. Процессы при таком обмене могут исполняться как на
одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет —
абстрактный объект, представляющий конечную точку соединения. Приложение
просто пишет данные в сокет; их дальнейшая буферизация, отправка и
транспортировка осуществляется используемым стеком протоколов и сетевой
аппаратурой. Чтение данных из сокета происходит аналогичным образом.
7
1.2.
Анализ требований к программным средствам
Функции программы «сервер» показаны в диаграмме вариантов использования
на рисунке 1.
Инициализация
работы
Завершить
работу
Пользователь
Рисунок 1 Диаграмма вариантов использования приложения
«сервер»
Описание вариантов использование приложения «сервер» приведено в таблице 1.
Таблица 1 Варианты использование приложения «сервер»
«Инициализация работы»
Пользователь
может
запустить
приложение «сервер».
«Завершить работу»
Пользователь может завершить работу
приложения «сервер».
Функции программы «клиент» показаны в диаграмме вариантов использования
на рисунке 2.
8
Ввести IP
адрес
Ввести имя
файла
Подключиться
к серверу
Отключиться
от сервера
Пользователь
Ввести
искомую
строку
Завершить
работу
100
80
Рисунок 2 Диаграмма вариантов использования
приложения «клиент»
60
Восток
Описание вариантов использование приложения «клиент» приведено
в таблице 2.
Запад
40
Север
20
Таблица 2 варианты использования приложения «клиент»
0
1 кв
«Ввести IP адрес»»
«Подключиться к серверу»
«Отключиться от сервера»
«Завершить работу»
«Ввести имя файла»
«Ввести искомую строку»
2 кв
3 кв
4 кв
Пользователь
может ввести IP адрес
сервера.
Пользователь может подключиться к
серверу.
Пользователь может отключиться от
сервера.
Пользователь может завершить работу
приложения «клиент».
Пользователь может ввести имя файла
для поиска строки.
Пользователь может ввести искомую
строку в файле.
9
1.3.
Описание реализуемых алгоритмов
Программа должна состоять из двух приложений (клиент и сервер).
Клиентов может быть несколько. Алгоритм программы будет включать в
себя этапы:
 Инициализация библиотеки для функционирования сокетов.
 Объявление объектов сокетов протокола TCP для передачи данных
по локальной сети.
 В приложении сервера происходит связывание сокета с локальным
адресом,
после
чего
сервер
переходит
в
режим
ожидания
подключений.
 В приложении «клиент» осуществляется ввод IP-адреса для
соединения с сервером. Клиент соединяется с сервером, если IP-адрес
введен корректно.
 При подключении клиента для него создаётся отдельный поток, в
котором осуществляется обработка запроса. Отдельный поток создаётся
для того, чтобы сервер одновременно мог обрабатывать запросы от
нескольких клиентов.
 Клиент отправляет запрос на поиск в файле искомой строки.
 В приложение «сервер» происходит открытие файла, считываение из
него информации и поиск в ней строки, отправка результатов поиска
приложению «клиент».
 В приложение «клиент» происходит получение результатов поиска,
после чего может осуществляться повторная отправка запроса или
отключение от приложения «сервер» или выход из приложения
«клиент».
Для передачи данных должны использоваться сокеты протокола TCP.
Все события, происходящие в каждом приложении, а именно:
инициализация библиотеки, создание сокета, подключение и отключение
клиента, прием и передача запросов, приём и передача файлов – должны
выводиться на экран.
10
1.4.
Анализ требований к интерфейсу пользователя
Интерфейс серверного приложения должен позволять:
 корректно завершить работу сервера.
 просматривать сообщения об инициализации библиотеки, создании
сокета, подключении клиента, получении запроса, отправке файла,
отключении клиента и возможных ошибках.
Интерфейс клиентского приложения должен позволять:
 ввести IP-адрес для подключения к приложению «сервер».
 отправить запрос на поиск строки в файле.
 принять результат от сервера и вывести его на экран.
 корректно завершить работу клиента.
 просматривать сообщения об инициализации библиотеки, создании
сокета, отправке запроса серверу, получении файла и возможных
ошибках в перечисленных выше действиях.
Для вывода сообщений, ввода IP «сервера», имени файла и искомой
строки,
следует выделить отдельные поля на форме. Для отправки
запроса, подключения к приложению «сервер» и выхода из приложения –
кнопки на форме и пункты главного меню.
2. Проектирование
2.1.
Проектирование программной модели
Схема взаимодействия программ представлена в приложении А.
Клиент и сервер взаимодействуют следующим образом:
 В приложении «клиент» пользователь вводит IP-адрес, по нажатию
кнопки подключения происходит подключение к серверу. После того как
пользователь введет имя файла и искомую строку он отправляется запрос
11
по поиску строки в файле по нажатию соотвествующей кнопки.
Приложение покажет сообщение об отправке запрос, и получив ответ от
сервера выведет результаты поиска, или сообщения об ошибках в данных
действиях.
С одним сервером может взаимодействовать несколько клиентов, для
этого для каждого подключившегося клиента создаётся поток (процесс), что
позволит обслуживать нескольких клиентов одновременно.
 Приложение «сервер», которое после успешной подготовки к
передаче и приёму данных находится в режиме ожидания подключения
клиентов, при подключении клиента выводит соответствующее сообщение
на экран и создается поток обработки запроса клиента. Сервер проводит
открытие файла и поиск в нем искомой строки, отправляет результаты
клиенту. При отключении клиента также выводится сообщение.
2.2.
Проектирование интерфейса пользователя
Исходя
из анализа требований
спроектирован
интерфейс
серверного
к интерфейсу пользователя, был
и
клиентского
приложений,
где
присутствуют поле вывода сообщений, кнопки для остановки работы
приложения, отправки запроса, поле ввода IP-адреса, искомой строки и имени
файла, главное меню дублирующее кнопки приложения.
Интерфейс приложения «сервер» показан на рисунке 3.
12
1
2
Рисунок 3 Интерфейс приложения «сервер»
На рисунке 3
1. Поле вывода сообщений о проделанных действиях или ошибках в этих
действиях.
2. Кнопка корректного завершения работы.
Интерфейс приложения «клиент» показан на рисунке 4.
13
1
2
3
4
5
6
7
8
Рисунок 4 Интерфейс приложения «клиент»
1. Главное меню приложения.
2. Поле вывода сообщений о проделанных действиях или ошибках в этих
действиях.
3. Поле ввода IP адреса.
4. Кнопка присоединения.
5. Кнопка отсоединения.
6. Поле ввода имени файла.
7. Поле ввода искомой строки.
8. Кнопка отправки запроса на поис строки в файле.
2.3.
Описание работы системы
Схема работы системы представлена в приложении Б.
Работа системы заключается в следующем
14
 Запускается серверное приложение, которое переходит в режим
ожидания
подключений
клиентов.
Затем
запускается
клиентское
приложение, в котором с клавиатуры вводится IP-адрес.
 В клиентском приложении после нажатия кнопки «Connect»
осуществляется вывод информации в поле вывода сообщений об
успешном
подключении
библиотеки
Winsock,
создании
сокета,
подключении к приложению «сервер» или об соответствующих ошибках.

Приложение «клиент» переходит в режим ожидания получения
сообщений от сервера в отдельном потоке.
 Сервер принимает нового клиента и ждет от него запроса.
 По нажатию кнопки «Find», происходит считывание данных с
полей «имя файла» и «искомая строка», формируется запрос серверу, на
экране клиента выводится сообщение об отправке или об ошибке отправки
этого запроса.
 Сервер получает от клиента запрос и выводит соответствующее
сообщение в поле вывода сообщений.
 Сервер осуществляет поиск файла и искомой строки в нем и
передает результаты клиенту.
 Клиент принимает сообщение о поиске и выводит результат на
экран.
 При
нажатии
пункта
главного
меню
«Disconnect»
клиент
отключается от сервера
 При нажатии пункта главного меню «Exit» клиент завершает свою
работу.
 Потеряв соединение с клиентом, сервер выводит сообщение о том,
что клиент отключился.
 При потери соединения сервером клиент выводит сообщение о том
что сервер отключился.
15
 При задержке ответного пакета клиенту на большое время, сервер
считается загруженным, и клиент отключается от него.
2.4.
Описание работы программы
Схема работы программ представлена в приложении В.
Для работы с сокетами сначала необходимо подключить библиотеку
Winsock с помощью функции WSAStartup().
Далее создаётся дейтаграмный сокет с помощью функции socket(), где
указывается семейство протоколов (AF_INET – Internet-протоколы), вид
сокета (SOCK_STREAM - потоковый) и вид используемого протокола
(IPPROTO_TCP – протокол TCP).
Для серверного приложения необходимо связать сокет с локальным
адресом функцией bind(), послав в неё структуру типа SOCKADDR_IN. В
этой структуре заполняются поля: sin_family = AF_INET (семейство
протоколов),
sin_port
htonl(INADDR_ANY).
=
htons(616)
Переменная
(порт),
INADDR_ANY
sin_addr.s_addr
разрешает
=
приём
данных ото всех источников, знающих порт и IP-адрес сервера. В
приложении клиента в поле sin_addr.s_addr указывается IP-адрес сервера,
а в поле sin_port номер порта сервера, установленный разработчиком.
Выполнив связывание, потоковый сервер переходит в режим
ожидания подключений, вызывая функцию listen (SOCKET s, int backlog),
где s - дескриптор сокета, а backlog - максимально допустимый размер
очереди сообщений.
Извлечение запросов на соединение из очереди осуществляется
функцией accept (), которая автоматически создает новый сокет, выполняет
связывание и возвращает его дескриптор, а в структуру sockaddr заносит
сведения о подключившемся клиенте (IP-адрес и порт). Если в момент
вызова accept очередь пуста, функция не возвращает управление до тех
пор, пока с сервером не будет установлено хотя бы одно соединение.
16
Клиент для установки соединения с удаленным узлом должен
вызвать функцию connect (SOCKET s, const struct sockaddr FAR* name, int
namelen) , где s - дескриптор сокета, name – указатель на структуру
SOCKADDR_IN, namelen – размер структуры.
Потоковые сокеты могут обмениваться с удаленным узлом данными,
вызывая
функции send () и recv ()
для
посылки
и
приема
данных
соответственно.
Сервер переходит в режим ожидания сообщений от клиента и принимает
данные с помощью функции recv(). После получения
запроса сервером
производится анализ пришедших данных, открытие файла поиск строки и
отсылка результата с помощью функции send(). После чего клиент может
повторно отправить запрос или завершить свою работу.
Завершение работы клиента осуществляется нажатием пункта
главного меню «Actions->Exit», после чего клиентское приложение
закрывает сокет и закрывается.
Завершение работы сервера осуществляется нажатием кнопки «Exit»,
после чего серверное приложение закрывает сокет и закрывается.
2.5.
Реализация
2.5.1.
Реализация серверного приложения
Полный код программы «сервер» представлен в приложении Д.
В результате проектирования интерфейса пользователя на форме
серверного приложения появилась кнопка «Exit», и поле вывода сообщений о
проделанных действиях или ошибках в этих действиях.
В обработчике загрузки формы находится создание главного потока в
котором реализуется:
 инициализация библиотеки Winsock с помощью функции WSAStartup(
0x202, &wsaData ), где указывается версия и подверсия библиотеки (2, 2)
и посылается пустая структура типа WSADATA;
17
 создание сокета с помощью функции socket(), где указывается семейство
протоколов (AF_INET – Internet-протоколы), вид сокета(SOCK_STREAM
- потоковый) и вид используемого протокола (IPPROTO_TCP – протокол
TCP);
 связывание сокета с локальным адресом функцией bind(), отправив в неё
структуру типа SOCKADDR_IN. В этой структуре заполняются поля:
sin_family = AF_INET (семейство протоколов), sin_port = htons(616)
(порт),
sin_addr.s_addr
=
htonl(INADDR_ANY).
Переменная
INADDR_ANY разрешает приём данных ото всех источников, знающих
порт и IP-адрес сервера;
 переход в режим ожидания подключений функцией listen (SOCKET s, int
backlog), где s - дескриптор сокета, а backlog - максимально допустимый
размер очереди сообщений.
 Создание потока для получения запросов на соединение.
 Извлечение
запросов
функцией accept(),
на
соединение
которая
из
очереди
автоматически
создает
осуществляется
новый
сокет,
выполняет связывание и возвращает его дескриптор. Происходит
создание нового потока для обработки клиента.
Успех или неудача всех вышеперечисленных действий выводится в
поле вывода сообщений. В новом потоке выполняется функция приёма
запроса и передачи результатов поиска строки в файле, в которой описано:
 Приём запроса c помощью функции recv()
 Анализ исходного запроса, вычленение имени файла и искомой строки
 Поиск искомой строки в файле
 Отправка результатов клиенту с помощью send().
В обработчике нажатия
закрытие формы.
кнопки «Exit» находится закрытие сокета и
18
2.5.2.
Реализация клиентского приложения
Полный код программы «клиент» представлен в приложении Г.
В результате проектирования интерфейса пользователя на форме
клиентского приложения появились кнопки «Connect», «Disconnect»,
«Find» и пункты меню «Connect», «Disconnect», «Find» и «Exit»; поля
ввода IP-адреса, поле вывода сообщений, поля ввода имени файла и
искомой строки.
В обработчике нажатия кнопк «Connect» находится:
 инициализация
библиотеки
с
Winsock
помощью
функции
WSAStartup(0x202, &wsaData), где указывается версия и подверсия
библиотеки (2, 2) и посылается пустая структура типа WSADATA;

создание сокета с помощью функции socket(), где указывается
семейство
протоколов
(AF_INET
–
Internet-протоколы),
вид
сокета(SOCK_STREEM) - потоковый и вид используемого протокола
(IPPROTO_TCP – протокол TCP);
 считывание IP-адреса и номера порта из поля ввода IP-адреса,
заполнение структуры SOCKADDR_IN для дальнейшей передачи
данных. В этой структуре заполняются поля: sin_family = AF_INET
(семейство протоколов), sin_port = htons(616) (порт), sin_addr.s_addr
= htonl(<IP-адрес сервера>).
 Присоединие сокета к серверу с помощью заполненной серверной
структуры и connect().
 Создание потока ждущего сообщений с сервера c помощью recv().
В обработчике нажатия кнопки «Find» находится:
 Считывание имени файла и искомой строки с полей формы,

Отправка сообщения серверу с помощью send().
19
В обработчике нажатия кнопки «Exit» находится закрытие сокета и
завершение работы приложения.
В обработчике нажатия кнопки «Disconnect» находится закрытие
сокета.
2.6.
Руководство оператора
2.6.1.
Серверное приложение
Для начала работы сервера пользователю нужно просто запустить
приложение. При успешном выполнении в поле вывода сообщений
появятся уведомления:
«Log init OK» - приложение успешно запустилось
«WSA init OK» – библиотека Winsock инициализирована.
«Socket OK» – сокет создан.
«Socket binded OK» – связывание сокета с локальным адресом успешно
«Socket listen OK» – переход в режим ожидания подключения.
Если какой-то из шагов закончился неудачей, то в поле вывода
сообщений появится соответствующие уведомления:
«WSA init error!» – ошибка инициализации библиотеки.
«Socket creating error!» – ошибка создания сокета.
«Socket binding error!» – ошибка связывания сокета с локальным адресом.
«Socket listen error!» – ошибка перехода в режим ожидания подключения.
При подключении клиента выводится сообщение:
«Client accepted» - клиент подключен.
«Clients count: …» - количество подключенных пользователей
При отключении клиента выводится сообщение:
«Client disconnected» -клиент отключен.
«Clients count: …»
20
«Can’t accept client» - ошибка accept() клиента.
При получении запроса от клиента выводится сообщение:
«Get filename: … Get find str: …» - получен запрос от клиента.
При открытии файла выводится:
«… finded in file: …» - Файл открыт, cтрока найдена.
«… not finded in file: …» - Файл открыт, строка не найдена.
Если произошла ошибка то
«… does not exist!» - Ошибка открытия файла.
Если клиент завершил работу, выводится сообщение:
«Client disconnected»
«Clients count:…» - количество подключенных пользователей.
2.6.2.
Клиентское приложение
Для работы с клиентским приложением пользователю необходимо:
 Запустить приложение:
«Log init OK» - приложение успешно запустилось
 Ввести IP-адрес сервера и нажать
кнопку «Connect».
Если
данные
введены корректно, то в поле вывода сообщений появится уведомление:
«WSA init OK» – библиотека Winsock инициализирована.
«Socket OK» – сокет создан.
«Socket connection OK» - сокет соединен
В случае неудачи появится уведомление:
«Socket connection error!» В случае некорректного ввода IP адреса.
«WSA init error!» – ошибка инициализации библиотеки.
«Socket creating error!» – ошибка создания сокета.
 Нажать кнопку «Find» для отправки запроса на поиск строки в файле.
21
 При
успешной
отправке
и
приеме
появится
сообщение:
«String find!» - строка найдена в файле.
«No such file!» – файл не существует.
«String not found» – строка не найдена в файле.
Иначе будет выведено сообщение:
«Server disconnected!» - сервер отключен.
«Server don't reply client!» - ответ сервера слишком долго не приходил, сервер
считается недоступным
3. Методика тестирования программы
В качестве проверки приложения используем функциональное тестирование.
Результаты тестирования приведены вприложение Г.
Способы тестирования приведены в таблице 3.
Таблица 3 Способы тестирования программы
Функция
Тест
Результат
Запуск сервера
Пользователь
Появилось окно сервера. В поле
запускает
вывода
исполняемый
сообщений
появились
файл результаты подготовки к приёму
приложения «сервер» запроса (рисунок 5)
Запуск клиента
Пользователь
Появилось
запускает
приложения (рисунок 6)
исполняемый
приложения
«клиент»
файл
окно
клиентского
22
Ввод
IP-адреса Пользователь вводит В
поле
вывода
сервера в окне IP-адрес в поле ввода появилось
клиента
сообщений
уведомление
об
и нажимает кнопку успешном подключении (рисунок
«Connect».
7)
В приложении сервера появилось
уведомление
о
подключении
клиента (рисунок 8)
Отправка
Пользователь
запроса серверу
нажимает
В
поле
вывода
сообщений
кнопку появилось уведомление о отправке
запроса серверу (рисунок 9)
«Find»
В приложение «сервер» в поле
вывода
сообщений
появилось
уведомление о полученном запросе
и
рузультат
поиска
строки
(рисунок 10)
Ввод неверного Пользователь вводит В
поле
вывода
сообщений
неверный IP-адрес в появилось сообщение об ошибке
IP-адреса
сервера в окне поле
клиента
ввода
нажимает
и подключения (рисунок 11)
кнопку
«Connect»
Ввод
Пользователь вводит В
отсуствующей
строку
строки
вывода
сообщений
появилось уведомление об ощибке
для отсуствующую
поиска в файле
поле
в поиска строки (рисунок 12)
заданном файле
нажимает
«Find»
кнопку
В
поле
вывода
сообщений
появилось уведомление об ошибке
поиска строки (рисунок 13)
23
Запуск второго Пользователь
В поле вывода сообщений клиента
клиента.
появилось
запускает
Подключение к исполняемый
серверу
уведомление
об
файл успешном подключении (рисунок
приложения
14)
«клиент». Вводит ip В приложении сервера появилось
адрес
и
нажимает уведомление
о
подключении
кнопку «Connect»
клиента (рисунок 15)
Завершение
Пользователь
Приложение клиента закрывается.
работы клиента
нажимает
кнопку
На сервере выводится сообщение
«Exit» в клиентском об отключении клиента (рисунок
приложении
16)
Запуск второго Пользователь
сервера
на повторно
Ошибка при связывании сокета с
запускает локальным адресом (рисунок 17)
одном
исполняемый
компьютере
приложения «сервер»
Сервер
файл
теряет Сервер теряет связь с Клиент
связь с сетью
сетью,
уведомляет
о
аварийно соединения (рисунок 18).
завершая работу.
Сервер завершает работу.
потере
24
Отсуствие
Пользователь вводит В
поле
файла у сервера. имя файла, которого появилось
вывода
сообщений
уведомление
об
явно не существует отправке запроса, получении ответа
на
сервере
нажимает
и о невозможности открыть файл
кнопку (рисунок 19)
«Find»
В приложение «сервер» принят
запрос на поиск строки в файле,
файл не найден (рисунок 20)
25
Заключение
В курсовом проекте выполнены анализ требований, проектирование и
реализация программных средств, которые позволили выполнить в полном объёме
поставленную задачу исследования механизмов межпроцессного взаимодействия в
сети, путём разработки клиент-серверного приложения.
Результаты тестирования, подтверждают, что разработанные программные
средства правильно выполняют заданные функции.
26
Список использованных источников
1. Ю.А. Щупак. Win32 API. Эффективная разработка приложений. – СПб, Питер,
2007.
2. Джонс Д. Оланд. Программирование в сетях Microsoft Windows – СПб, Питер,
2002.
3. MSDN for Visual Studio 2005.
4. Т. А. Павловская. C/C++. Программирование на языке высокого уровня. – СПб,
Питер, 2004
5. А. Л. Марченко. C++. Бархатный путь - Горячая Линия - Телеком, 2006.
27
Приложение А.
(обязательное)
Схема взаимодействия программ
28
Клавиатура
Сервер
Дисплей
Канал связи
(TCP сокет)
Клавиатура 1
Канал связи 1
(TCP сокет)
Канал связи N
(TCP сокет)
Клиент 1
Клиент N
Дисплей 1
Изм Лист
№ д о ку м .
Р аз р аб . Б а ш е в А . С
Гурин Е.И.
Пр о в.
Н.Контр.
Утв.
Подп. Дат
а
Дисплей N
Клавиатура N
ПГУ 230105–7КП092.01 ПЗ
Лит.
Схема взаимодействия
программ
Лист Листов
28
Гр.09ВП2
55
29
Приложение Б.
(обязательное)
Схема работы системы.
30
Начало
Запуск сервера
Запуск клиента
Ввод IP Адреса
сервера
Клавиатура
Подключение к
серверу
Ввод имени файла,
Ввод искомой строки
Клавиатура
Отправка запроса
серверу
Вывод
сообщения об
отправке запроса
Получение запроса
сервером
Вывод
сообщения о
получении
запроса
Открытие файла
сервером
Чтение содержимого
файла в строку
(файловая строка)
Поиск искомой
строки в файловой
строке
Вывод
результатов
поиска
Отправка
результатов поиска
клиенту
Получение
результатов поиска
клиентом
Вывод
результатов
поиска
Конец
Изм Лист
№ д о ку м .
Р аз р аб . Б а ш е в А . С .
Пр о в.
Гурин Е.И.
Подп. Дат
а
ПГУ 230105–7КП092.03 ПЗ
Лит.
Лист Листов
30
Схема работы системы
Н.Контр.
Утв.
Гр.09ВП2
55
31
Приложение В.
(обязательное)
Схема работы программ
server_thread()
client_thread()
Начало
Начало
Начало
Инициализация
Winsock
(WSAStartup())
Цикл извлечения
запросов на
подключение
(accept())
(1)
Цикл приема
запросов клиента
(recv())
(1)
Создание сокета
TCP
(socket())
32
Нет
Запрос на
подключение
получен?
Запрос клиента
получен?
Да
Связывание сокета с
локальным адресом
(bind())
Создание потока
обработки клиентов с
функцией
client_thread()
Переход в режим
ожидания
подключений
(listen())
Открытие файла
Да
Сервер не
остановлен
пользователем?
Создание потока
приема клиентов
(CreateThread())
c функцией
server_thread()
Считывание файла в
строку
(файловая строка)
Нет
(1)
Конец
Поиск в файловой
строке искомой
строки
Отправка
результатов клиенту
(send())
Закрытие сокета
сервера
(closesocket())
Конец
(1)
Конец
Изм Лист
№ д о ку м .
Р аз р аб . Б а ш е в А . С .
Гурин Е.И.
Пр о в.
Н.Контр.
Утв.
Подп. Дат
а
ПГУ 230105–7КП092.01 ПЗ
Сетевое клиент-серверное
приложение.
Сервер.
Схема работы программ.
Лит.
Лист Листов
32
Гр.09ВП2
55
33
client_thread()
Начало
33
Начало
Инициализация
Winsock
(WSAStartup())
Цикл приема
сообщений сервера
(recv())
(1)
Создание сокета
TCP
(socket())
Нет
Сообщение
сервера
получено?
Ввод IP сервера
Клавиатура
Да
Соединение сокета с
сервером (connect())
Вывод
результатов
запроса
Разбор сообщения
Создание потока
читающего
сообщения сервера с
функцией
client_thread()
Цикл приема
отправки запросов
серверу
(1)
(1)
Ввод имени файла и
искомой строки
Клавиатура
Отправка запроса
серверу
(send())
Пользователь не
завершил работу
клиента?
Нет
Конец
Да
(1)
Закрытие сокета
клиента
(closesocket())
Конец
Изм Лист
№ д о ку м .
Р аз р аб . Б а ш е в А . С .
Гурин Е.И.
Пр о в.
Н.Контр.
Утв.
Подп. Дат
а
ПГУ 230105–7КП092.01 ПЗ
Сетевое клиент-серверное
приложение.
Клиент.
Схема работы программ.
Лит.
Лист Листов
33
Гр.09ВП2
55
34
Приложение Г.
(обязательное)
Результаты тестирования.
35
Рисунок 5 Запуск приложения «сервер»
Рисунок 6 Запуск приложения «клиент»
36
Рисунок 7 Подключение к «серверу»
Рисунок 8 Подключение нового клиента
37
Рисунок 9 Отправка запроса «серверу»
Рисунок 10 Получен запрос от клиента
38
Рисунок 11 Ввод неверного ip адреса
Рисунок 12 Ввод отсуствующей строки
39
Рисунок 13 Строка не найдена в файле
Рисунок 11 Запуск второго приложения «клиент»
40
Рисунок 12 Подключение второго клиента
Рисунок 13 Отключение клиента
Рисунок 14 Запуск второго приложение «сервер»
41
Рисунок 15 Аварийное завершение работы сервера
Рисунок 16 Ввод несуществующего файла
42
Рисунок 17 Файл не найден на сервере
43
Приложение Д.
(обязательное)
Код программ.
44
Клиент
#define ID_CONNECT_BUTTON 1
#define ID_FIND_BUTTON
2
#define ID_DISCONNECT_BUTTON 3
#define ID_CONNECTION_MENU 100
#define ID_CONNECT_MENU 101
#define ID_DISCONNECT_MENU 102
#define ID_ACTION_MENU 200
#define ID_FIND_MENU 201
#define ID_EXIT_MENU 202
#define WINDOW_TITLE L"Kurs Client by Bashev A.S. 09vp2"
#define WINDOW_CLASS L"client_window"
#define WSA_VERSION 0x202
#define SERVER_PORT 616
#define BUFFER_SIZE 1024
#define WINDOW_WIDTH 415
#define WINDOW_HEIGHT 320
#define FILE_NOT_FOUND 2
#define KEEP_ALIVE 3
#define CHECK_WAIT 2000
#define DELIM L"@"
#include <string>
#include <windows.h>
#include <tchar.h>
#include <string.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
static HWND EDIT_BOX_FILE;
static HWND EDIT_BOX_STR;
static HWND EDIT_BOX_IP;
static HWND LOG_LABEL;
static HWND CONNECT_BUTTON;
static HWND FIND_BUTTON;
static HWND DISCONNECT_BUTTON;
static bool REQUEST_SEND = false;
static bool REPLY_GET = false;
static int REPLY_TIME = 0;
static wstring LOG = L"Log init OK\r\n";
static SOCKET CLIENT_SOCKET = INVALID_SOCKET;
static void show_error_box(LPWSTR msg)
{
MessageBox(NULL, msg, L"Error!", MB_ICONERROR | MB_OK);
if(CLIENT_SOCKET != SOCKET_ERROR || CLIENT_SOCKET != INVALID_SOCKET)
{
closesocket(CLIENT_SOCKET);
CLIENT_SOCKET = INVALID_SOCKET;
}
EnableWindow(CONNECT_BUTTON, TRUE);
EnableWindow(FIND_BUTTON, FALSE);
EnableWindow(EDIT_BOX_STR, FALSE);
EnableWindow(EDIT_BOX_FILE, FALSE);
EnableWindow(DISCONNECT_BUTTON, FALSE);
EnableWindow(EDIT_BOX_IP, TRUE);
WSACleanup();
PostQuitMessage(EXIT_SUCCESS);
}
static void create_menu(HWND main)
45
{
HMENU menu
= CreateMenu();
HMENU hsmConnection, hsmAction;
hsmConnection
= CreatePopupMenu();
hsmAction = CreatePopupMenu();
MENUITEMINFO mii;
mii.hSubMenu = NULL;
mii.cbSize
= sizeof(MENUITEMINFO);
mii.fMask
= MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU;
mii.fType
= MFT_STRING;
mii.dwTypeData = TEXT("Connect");
mii.cch
= 7;
mii.wID
= ID_CONNECT_MENU;
InsertMenuItem(hsmConnection, 0, TRUE, (LPCMENUITEMINFO) &mii);
mii.dwTypeData = TEXT("Disconnect");
mii.cch
= 10;
mii.wID
= ID_DISCONNECT_MENU;
InsertMenuItem(hsmConnection, 1, TRUE, (LPCMENUITEMINFO) &mii);
mii.dwTypeData = TEXT("Find");
mii.cch
= 4;
mii.wID
= ID_FIND_MENU;
InsertMenuItem(hsmAction, 0, TRUE, (LPCMENUITEMINFO) &mii);
mii.dwTypeData = TEXT("Exit");
mii.cch
= 4;
mii.wID
= ID_EXIT_MENU;
InsertMenuItem(hsmAction, 1, TRUE, (LPCMENUITEMINFO) &mii);
mii.dwTypeData = TEXT("Connection");
mii.cch
= 10;
mii.wID
= ID_CONNECTION_MENU;
mii.hSubMenu = hsmConnection;
InsertMenuItem(menu, 0, TRUE, (LPCMENUITEMINFO) &mii);
mii.dwTypeData = TEXT("Actions");
mii.cch
= 7;
mii.wID
= ID_ACTION_MENU;
mii.hSubMenu = hsmAction;
InsertMenuItem(menu, 1, TRUE, (LPCMENUITEMINFO) &mii);
SetMenu(main, menu);
}
static void show_result_box(LPWSTR msg)
{
MessageBox(NULL, msg, L"Result", MB_ICONINFORMATION | MB_OK);
}
static void add_line_to_log(wstring line)
{
LOG = LOG + line + L"\r\n";
SendMessage(LOG_LABEL, WM_SETTEXT, NULL, (LPARAM)LOG.c_str());
}
static DWORD WINAPI server_check_thread(LPVOID lpParam)
{
SOCKET client_socket = *(SOCKET*) lpParam;
char msg = KEEP_ALIVE;
while(true)
{
if(send(client_socket,&msg, sizeof(char), 0) == SOCKET_ERROR)
46
{
add_line_to_log(L"Server disconnected!");
show_error_box(L"Server disconnected!");
break;
}
Sleep(CHECK_WAIT);
if(REQUEST_SEND && !REPLY_GET)
{
REPLY_TIME += CHECK_WAIT;
if(REPLY_TIME == 2*CHECK_WAIT)
{
show_error_box(L"Server don't reply client!");
REQUEST_SEND = false;
REPLY_TIME = 0;
}
}
if(REQUEST_SEND && REPLY_GET)
{
REQUEST_SEND = false;
REPLY_TIME = 0;
REPLY_GET = FALSE;
}
}
return EXIT_SUCCESS;
}
static DWORD WINAPI client_thread(LPVOID lpParam)
{
char result = EXIT_FAILURE;
while(recv(CLIENT_SOCKET, &result, sizeof(result), 0) != SOCKET_ERROR)
{
switch (result)
{
case EXIT_SUCCESS:
add_line_to_log(L"String find!");
show_result_box(L"String find!");
break;
case FILE_NOT_FOUND:
add_line_to_log(L"No such file!");
show_result_box(L"No such file!");
break;
case EXIT_FAILURE:
add_line_to_log(L"String not found");
show_result_box(L"String not found");
break;
}
REPLY_GET = TRUE;
}
add_line_to_log(L"Server disconnected!");
show_error_box(L"Server disconnected!");
return EXIT_FAILURE;
}
static void init_client(wstring ip)
{
WSADATA wsa_data;
if (WSAStartup(WSA_VERSION, &wsa_data))
show_error_box(L"WSA init error!");
add_line_to_log(L"WSA init OK");
if ((CLIENT_SOCKET = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
show_error_box(L"Socket creating error!");
add_line_to_log(L"Socket OK");
string _ip (ip.begin(), ip.end());
47
sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(SERVER_PORT);
server_address.sin_addr.s_addr = inet_addr(_ip.c_str());
if (connect(CLIENT_SOCKET,(sockaddr*)&server_address, sizeof(server_address)))
show_error_box(L"Socket connection error!");
add_line_to_log(L"Socket connection OK");
EnableWindow(CONNECT_BUTTON, FALSE);
EnableWindow(FIND_BUTTON, TRUE);
EnableWindow(EDIT_BOX_STR, TRUE);
EnableWindow(EDIT_BOX_FILE, TRUE);
EnableWindow(EDIT_BOX_IP, FALSE);
EnableWindow(DISCONNECT_BUTTON, TRUE);
DWORD client_thread_id;
CreateThread(NULL, 0, client_thread, NULL, 0, &client_thread_id);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(EXIT_SUCCESS);
break;
case WM_CREATE:
{
CreateWindow(
L"STATIC",
L"Input server IP below",
WS_CHILD|WS_VISIBLE|SS_CENTER,
WINDOW_WIDTH / 2,
0,
200,
25,
hWnd,
NULL,
NULL,
NULL);
LOG_LABEL = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT",
LOG.c_str(),
WS_CHILD|WS_VISIBLE|
ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_READONLY,
0,
0,
WINDOW_WIDTH / 2,
WINDOW_HEIGHT,
hWnd,
NULL,
GetModuleHandle(NULL),
NULL);
EDIT_BOX_IP = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT",
L"127.0.0.1",
WS_CHILD|WS_VISIBLE,
WINDOW_WIDTH / 2,
48
25,
200,
50,
hWnd,
NULL,
GetModuleHandle(NULL),
NULL);
CONNECT_BUTTON = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"BUTTON",
L"Connect",
WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
WINDOW_WIDTH / 2,
75,
100,
50,
hWnd,
(HMENU) ID_CONNECT_BUTTON,
GetModuleHandle(NULL),
NULL);
EDIT_BOX_FILE = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT",
L"Insert filename here",
WS_CHILD|WS_VISIBLE,
WINDOW_WIDTH / 2,
125,
200,
50,
hWnd,
NULL,
GetModuleHandle(NULL),
NULL);
EDIT_BOX_STR = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT",
L"Insert search str here",
WS_CHILD|WS_VISIBLE,
WINDOW_WIDTH / 2,
175,
200,
50,
hWnd,
NULL,
GetModuleHandle(NULL),
NULL);
FIND_BUTTON = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"BUTTON",
L"Find",
WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
WINDOW_WIDTH / 2,
225,
200,
50,
hWnd,
(HMENU) ID_FIND_BUTTON,
49
GetModuleHandle(NULL),
NULL);
DISCONNECT_BUTTON = CreateWindowEx
(WS_EX_CLIENTEDGE,
L"BUTTON",
L"Disconnect",
WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
WINDOW_WIDTH / 2 + 100,
75,
100,
50,
hWnd,
(HMENU) ID_DISCONNECT_BUTTON,
GetModuleHandle(NULL),
NULL);
EnableWindow(DISCONNECT_BUTTON, FALSE);
EnableWindow(FIND_BUTTON, FALSE);
EnableWindow(EDIT_BOX_FILE, FALSE);
EnableWindow(EDIT_BOX_STR, FALSE);
}
break;
case WM_COMMAND:
{
if(LOWORD(wParam) == ID_FIND_BUTTON || LOWORD(wParam) == ID_FIND_MENU)
{
if(CLIENT_SOCKET == INVALID_SOCKET)
return EXIT_SUCCESS;
wchar_t buffer[BUFFER_SIZE];
SendMessage(EDIT_BOX_FILE, WM_GETTEXT, BUFFER_SIZE * sizeof(wchar_t), (LPARAM) buffer);
wstring to_send = wstring(buffer);
SendMessage(EDIT_BOX_STR, WM_GETTEXT, BUFFER_SIZE * sizeof(wchar_t), (LPARAM) buffer);
wstring file_str = wstring(buffer);
wstring sep = wstring(DELIM);
to_send = to_send.append(sep).append(file_str);
string _to_send (to_send.begin(), to_send.end());
if(send(CLIENT_SOCKET, (const char*) _to_send.c_str(), (int) _to_send.length() + 1, 0)==
SOCKET_ERROR)
show_error_box(L"Can't send data to server!");
add_line_to_log(L"Send request to server");
REQUEST_SEND = true;
}
if(LOWORD(wParam) == ID_CONNECT_MENU || LOWORD(wParam) == ID_CONNECT_BUTTON)
{
if(CLIENT_SOCKET == INVALID_SOCKET)
{
wchar_t buffer[BUFFER_SIZE];
SendMessage(EDIT_BOX_IP, WM_GETTEXT, BUFFER_SIZE * sizeof(wchar_t), (LPARAM) buffer);
wstring ip = wstring(buffer);
init_client(ip);
}
}
if((LOWORD(wParam)) == ID_EXIT_MENU)
{
closesocket(CLIENT_SOCKET);
WSACleanup();
PostQuitMessage(EXIT_SUCCESS);
}
50
if(LOWORD(wParam)== ID_DISCONNECT_MENU || LOWORD(wParam) == ID_DISCONNECT_BUTTON)
{
if(CLIENT_SOCKET == INVALID_SOCKET)
return EXIT_SUCCESS;
add_line_to_log(L"Client disconnected");
closesocket(CLIENT_SOCKET);
CLIENT_SOCKET = INVALID_SOCKET;
WSACleanup();
EnableWindow(CONNECT_BUTTON, TRUE);
EnableWindow(FIND_BUTTON, FALSE);
EnableWindow(EDIT_BOX_STR, FALSE);
EnableWindow(EDIT_BOX_FILE, FALSE);
EnableWindow(EDIT_BOX_IP, TRUE);
EnableWindow(DISCONNECT_BUTTON, FALSE);
}
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return EXIT_SUCCESS;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize
= sizeof(WNDCLASSEX);
wc.style
= 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon
= LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = WINDOW_CLASS;
wc.hIconSm
= LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
show_error_box(L"Window registration error!");
return EXIT_FAILURE;
}
HWND hwnd;
hwnd = CreateWindow
(
WINDOW_CLASS,
WINDOW_TITLE,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
WINDOW_WIDTH,
WINDOW_HEIGHT,
NULL, NULL, hInstance, NULL
);
if(!hwnd)
{
show_error_box(L"Window creation error!");
return EXIT_SUCCESS;
}
51
create_menu(hwnd);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > EXIT_SUCCESS)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
Сервер
#define WINDOW_TITLE L"Kurs Server by Bashev A.S. 09vp2"
#define WINDOW_CLASS L"server_window"
#define ID_EXIT_BUTTON
100
#define WINDOW_WIDTH 300
#define WINDOW_HEIGHT 350
#define BUFFER_SIZE 1024
#define WSA_VERSION 0x202
#define SERVER_PORT 616
#define SERVER_HOST "127.0.0.1"
#define FILE_NOT_FOUND 2
#define KEEP_ALIVE 3
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
#include <windows.h>
#include <tchar.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
static HWND LOG_LABEL;
static wstring LOG = L"Log init OK\r\n";
static SOCKET SERVER_SOCKET = INVALID_SOCKET;
static int CLIENTS_COUNT = 0;
static char find_str_in_file(wstring file_name, string find_str)
{
ifstream file;
file.open(file_name.c_str(), ios::ate | ios::binary | ios::in);
if (!file.is_open())
return FILE_NOT_FOUND;
int file_size = (int) file.tellg();
file.seekg (0, ios::beg);
char* buffer = new char [file_size];
file.read (buffer, file_size);
file.close();
string file_contents(buffer);
delete [] buffer;
if(file_contents.find(find_str) == string::npos)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
static void show_error_box(LPWSTR msg)
{
MessageBox(NULL, msg, L"Error!", MB_ICONERROR | MB_OK);
52
if(SERVER_SOCKET != SOCKET_ERROR || SERVER_SOCKET != INVALID_SOCKET)
{
closesocket(SERVER_SOCKET);
SERVER_SOCKET = INVALID_SOCKET;
}
WSACleanup();
PostQuitMessage(EXIT_SUCCESS);
}
static void show_info_box(LPWSTR msg)
{
MessageBox(NULL, msg, L"Server reply", MB_ICONINFORMATION | MB_OK);
}
static void add_line_to_log(wstring line)
{
LOG = LOG + line + L"\r\n";
SendMessage(LOG_LABEL, WM_SETTEXT, NULL, (LPARAM)LOG.c_str());
}
static DWORD WINAPI client_thread(LPVOID lpParam)
{
add_line_to_log (L"Client accepted");
stringstream ss;
ss << "Clients count: " << ++CLIENTS_COUNT;
string clients_count = ss.str();
add_line_to_log(wstring(clients_count.begin(), clients_count.end()));
char buffer[BUFFER_SIZE];
SOCKET client_socket = *(SOCKET*) lpParam;
while(recv(client_socket, (char*)&buffer[0], BUFFER_SIZE, 0) != SOCKET_ERROR)
{
if(buffer[0] == KEEP_ALIVE)
continue;
string line (buffer);
size_t end_part1 = line.find_first_of('@');
string file_name = line.substr(0, end_part1);
string find_str = line.substr(end_part1 + 1);
wstring wfile_name(file_name.begin(), file_name.end());
add_line_to_log(L"Get filename: " + wfile_name);
wstring wfind_str(find_str.begin(), find_str.end());
add_line_to_log(L"Get find str: " + wfind_str);
char res = find_str_in_file(wfile_name, find_str);
wstring info;
switch (res)
{
case EXIT_SUCCESS:
info = L"\"" + wfind_str + L"\" finded in file: " + wfile_name;
add_line_to_log(info);
break;
case FILE_NOT_FOUND:
info = wfile_name + L" does not exist!";
add_line_to_log(info);
break;
case EXIT_FAILURE:
info = L"\"" + wfind_str + L"\" not finded in file: " + wfile_name;
add_line_to_log(info);
break;
default:
break;
}
if(send(client_socket, &res, sizeof(res), 0) == SOCKET_ERROR)
break;
}
53
add_line_to_log (L"Client disconnected");
ss.str(string());
ss.clear();
ss << "Clients count: " << --CLIENTS_COUNT;
clients_count = ss.str();
add_line_to_log(wstring(clients_count.begin(), clients_count.end()));
closesocket(client_socket);
return EXIT_FAILURE;
}
static DWORD WINAPI server_thread(LPVOID lpParam)
{
SOCKET accepted_socket = INVALID_SOCKET;
while(true)
{
if ((accepted_socket = accept(SERVER_SOCKET, NULL, NULL)) == INVALID_SOCKET)
{
show_error_box(L"Can't accept client!");
break;
}
DWORD client_thread_id;
CreateThread(NULL, 0, client_thread, &accepted_socket, 0, &client_thread_id);
}
return EXIT_SUCCESS;
}
static void init_server()
{
WSADATA wsaData;
if (WSAStartup(WSA_VERSION, &wsaData))
show_error_box(L"WSA init error!");
add_line_to_log(L"WSA init OK");
if ((SERVER_SOCKET = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
show_error_box(L"Socket creating error!");
add_line_to_log(L"Socket OK");
sockaddr_in server_info;
server_info.sin_family = AF_INET;
server_info.sin_addr.s_addr = inet_addr(SERVER_HOST);
server_info.sin_port = htons(SERVER_PORT);
server_info.sin_addr.s_addr = INADDR_ANY;
if(bind(SERVER_SOCKET, (SOCKADDR*) &server_info, sizeof(server_info)) == SOCKET_ERROR)
show_error_box(L"Socket binding error!");
add_line_to_log(L"Socket binded OK");
if (listen(SERVER_SOCKET, SOMAXCONN) == SOCKET_ERROR)
show_error_box(L"Socket listen error!");
add_line_to_log(L"Socket listen OK");
DWORD client_thread_id;
CreateThread(NULL, 0, server_thread, NULL, 0, &client_thread_id);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
54
PostQuitMessage(EXIT_SUCCESS);
break;
case WM_CREATE:
{
init_server();
LOG_LABEL = CreateWindowEx(WS_EX_CLIENTEDGE,
L"EDIT",
LOG.c_str(),
WS_CHILD|WS_VISIBLE|
ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|ES_READONLY,
0,
0,
WINDOW_WIDTH,
WINDOW_HEIGHT - 100,
hWnd,
NULL,
GetModuleHandle(NULL),
NULL);
CreateWindowEx(NULL,
L"BUTTON",
L"Exit",
WS_VISIBLE|
WS_CHILD|BS_DEFPUSHBUTTON,
0,
WINDOW_HEIGHT - 100,
WINDOW_WIDTH,
90,
hWnd,
(HMENU)ID_EXIT_BUTTON,
GetModuleHandle(NULL),
NULL);
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case ID_EXIT_BUTTON:
show_error_box(L"Server exit!");
break;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return EXIT_SUCCESS;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize
= sizeof(WNDCLASSEX);
wc.style
= 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon
= LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor
= LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
55
wc.lpszMenuName = NULL;
wc.lpszClassName = WINDOW_CLASS;
wc.hIconSm
= LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
show_error_box(L"Register window class error!");
HWND hwnd = CreateWindow
(
WINDOW_CLASS,
WINDOW_TITLE,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
WINDOW_WIDTH,
WINDOW_HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if(!hwnd)
show_error_box(L"Create window error!");
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > EXIT_SUCCESS)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
Документ
Категория
Программирование, Базы данных
Просмотров
21
Размер файла
844 Кб
Теги
kursagotov
1/--страниц
Пожаловаться на содержимое документа