- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C# для профессионалов. Том II - Симон Робинсон
Шрифт:
Интервал:
Закладка:
public void Start() {
ReadQuotes();
listenerThread = new Thread(new ThreadStart(this.Listener));
listenerThread.Start();
}
Функция потока выполнения Listener() создает экземпляр TCPListener. В методе AcceptSocket() ожидается соединение клиента. Как только клиент соединяется, AcceptSocket() возвращает управление с сокетом, связанным с клиентом. Метод GetRandomQuoteOfTheDay() вызывается для отправки возвращаемой случайной цитаты клиенту с помощью socket.Send():
protected void Listener() {
listener = new TcpListener(port);
listener.Start();
while (true); {
Socket socket = listener.AcceptSocket();
if (socket == null) {
return;
}
string message = GetRandomQuoteOfTheDay();
UnicodeEncoding encoder = new UnicodeEncoding();
byte [] buffer = encoder.GetBytes(message);
socket.Send(buffer, buffer.Length, 0);
socket.Close();
}
}
Помимо Start() существуют другие методы для управления службой: Stop(), Suspend() и Resume():
public void Stop() {
listener.Stop();
}
public void Suspend() {
listenerThread.Suspend();
}
public void Resume() {
listenerThread.Resume();
}
Методом, который будет открыто доступным, является RefreshQuotes(). Если содержащий цитаты файл изменяется, то запускается повторное чтение данного файла с помощью этого метода:
public void RefreshQuotes() {
ReadQuotes();
}
}
}
Прежде чем разрабатывать службу для нашего сервера, полезно будет создать тестовую программу, которая имеет экземпляр QuoteServer и вызывает Start(). Таким образом можно протестировать функциональность без необходимости обрабатывать специфические для службы вопросы. Можно сконцентрироваться на создании требуемой функциональности. Этот тестовый сервер должен запускаться вручную и код легко просматривается с помощью отладчика.
Тестовая программа является консольным приложением C#. Мы ссылаемся на сборку класса QuoteServer. Содержащий цитаты класс копируется в каталог с:wrox (или нужно изменить аргумент конструктора для определения, куда копируется файл). После вызова конструктора мы обращаемся к методу Start() экземпляра QuoteServer.Start() возвращает управление сразу после создания потока выполнения, поэтому консольное приложение продолжает выполняться до тех пор, пока не будет нажата клавиша Return:
static void Main(string[] args) {
QuoteServer qs = new QuoteServer(@"c:wroxquotes.txt", 4567);
qs.Start();
Console.WriteLine("Hit return to exit");
Console.ReadLine();
qs.Stop();
}
Отметим, что QuoteServer с помощью этой программы будет выполняться на порте 4567 на localhost и необходимо использовать эти настройки позже на клиенте.
Пример TcpClient
Клиент является простым приложением Windows, где можно вводить имя хоста и номер порта сервера. Это приложение использует класс TCPClient для соединения с функционирующим сервером и получения возвращаемого сообщения для вывода его в текстовом поле. Внизу формы выводится статусная строка:
В этом коде используются инструкции using:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
Мы также включаем ссылку на файл QuoteServer.dll. Оставшаяся часть кода автоматически создается в IDL, поэтому он здесь не будет рассматриваться подробно. Основная функциональность клиента находится в обработчике нажатия кнопки Get Quote:
protected void buttonQuote_Click(object sender, System.EventArgs e) {
statusBar.Text = "";
string server = textBoxHostname.Text;
try {
int port = Convert.ToInt32(textBoxPortNumber.Text);
} catch (FormatException ex) {
statusBar.Text = ex.Message; return;
}
TcpClient client = new TcpClient();
try {
client.Connect(
textBoxHostname.Text, Convert.ToInt32(textBoxPortNumber.Text));
NetworkStream stream = client.GetStream();
byte[] buffer = new Byte[1024];
int received = stream.Read(buffer, 0, 1024);
if {received <= 0) {
statusBar.Text = "Read failed"; return;
}
texBoxQuote.Text = Encoding.Unicode.GetString(buffer);
} catch (SocketException ex) {
statusBar.Text = ex.Message;
} finally {
client.close();
}
}
Запустив тестовый сервер и клиент этого оконного приложения, можно протестировать функциональность. Успешное выполнение может дать следующий результат при использовании указанных на экране настроек:
Добавим серверу функциональность службы. Программа уже выполняется, что же нужно еще сделать? Необходимо, чтобы серверная программа автоматически запускалась во время начальной загрузки системы без какого-либо пользователя, зарегистрировавшегося в системе, и мы хотим управлять ею с помощью служебных управляющих программ.
Проект Windows Service
Используя новый мастер проектов для C# Windows Services, можно теперь начать создавать службу Windows. Будьте внимательны, чтобы не выбрать проект Web Service.
Службы Web рассматриваются в главе 17.
После нажатия OK для создания приложения Windows Service появится окно проектировщика, как в приложениях Windows Forms, но здесь нельзя вставлять компоненты Windows Forms. Окно проектировщика будет использоваться для добавления других компонентов, таких как счетчики производительности и регистрации событий: Выбор свойств этой службы открывает окно редактора свойств:
Сконфигурируем свойства службы:
□ AutoLog означает, что события автоматически регистрируются для запуска и остановки службы.
□ CanPauseAndContinue, CanShutdown и CanStop означают, что служба может обрабатывать специальные запросы pause, continue, shutdown и stop.
□ ServiceName является именем службы, которое записывается в реестр и используется для управления службой.
□ CanHandlePowerEvent является допустимым параметром для служб, работающих на системе Windows 2000. Мы поговорим о параметрах power позже.
По умолчанию используется имя службы WinService1 независимо от названия проекта. Можно установить только одну службу WinService1. Если возникает ошибка установки во время процесса тестирования, то причина может быть в этом. Проверьте, что имя службы изменено на более подходящее в начале разработки службы.
Изменение этих свойств с помощью редактора свойств задает значения нашего класса, производного из ServiceBase, в методе InitializeComponent(). Мы уже знаем этот метод из приложений Windows Forms. Со службами он используется аналогичным образом.
Мастер создаст код, но мы изменим имя файла на QuoteService.cs, имя пространства имен на Wrox.ProfessionalCSharp, а имя класса на QuoteService. Мы подробно рассмотрим этот код позже, а пока остановимся на классе ServiceBase.
Класс ServiceBase
Класс ServiceBase является базовым для всех служб .NET. Наш класс QuoteService выводится из ServiceBase. Этот класс общается со служебным управляющим менеджером при помощи недокументированного вспомогательного класса System.ServiceProcess.NativeMethods, который служит просто классом-оболочкой для вызовов API Win32. Этот класс закрытый, поэтому мы не можем его использовать.
Следующая диаграмма последовательностей показывает взаимодействие SCM — класса QuoteService и классов из пространства имен System.ServiceProcess. На диаграмме последовательностей просматриваются вертикальные линии жизни объектов и коммуникация, проходящая в горизонтальном направлении. Коммуникация упорядочена по времени сверху вниз:
SCM запускает процесс службы. Вначале вызывается метод Main(). В методе Main() нашей службы вызывается метод Run() базового класса ServiceBase. Run() регистрирует метод ServiceMainCallback() с помощью NativeMethods.StartServiceCtrlDispatcher() в SCM и записывает вход в журнал событий.
Следующий шаг — SCM вызывает зарегистрированный метод ServiceMainCallback() в нашей программе службы. ServiceMainCallback сам регистрирует обработчик с помощью NativeMethods.RegisterServiceCtrlHandler[Ex]() и задает статус службы в SCM. Затем вызывается метод OnStart(), в котором мы должны реализовать код запуска. Если OnStart() выполнился успешно, то значение ресурса для StartSuccessful записывается в журнал событий.
Обработчик реализуется в методе ServiceCommandCallback(). SCM вызывает этот метод, когда служба запрашивает изменения. Метод ServiceCommandCallback() направляет запросы далее в OnPause(), OnContinue(), OnStop(), OnCustomCommand() и OnPowerEvent().