Клиентская часть

// Настройка клиентского приложения, отправляющего пакеты на сервер и считывающего

// пакеты с серверного приложения.

using System;

using System.Drawing;

using System.Collection;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.Net;

using System.Net.Sockets;

using System.Threading;

// Запуск клиента UDP

public class Client: System.Windows.Forms.Form

{

TextBox inputTextBox, displayTextBox;

UdpClient client;

IPEndPoint receivePoint;

Container components = null;

public Client()// Конструктор по умолчанию

{

InitializeComponent();

receivePoint = new IPEndPoint(new IPAddress(0), 0);

client = new UdpClient(5001);

Thread thread = new Thread(new ThreadStart(WaitForPackets));

thread.Start();

}

// Код сгенерированный Visual Studio.NET

[STAThread]

static void Main(){ Application.Run(new Client)); }

// Закрытие клиентского приложения

protected void Сlient_Closing(object sender, CancelEventArgs e)

{ Environment.Exit(Environment.ExitCode)); }

// Отправка пакета

protected void inputTextBox_KeyDown(object sender, KeyEventArgs e)

{

if(e.KeyCode == Keys.Enter)

{

// Создание пакета (дэйтаграммы) в виде строки

string packet = inputTextBox.Text;

displayTextBox.Text += "r\n\Отсылаемый пакет содержит: + packet;

// Преобразование пакетов в массив байтов

byte[] data = Sestem.textEncoding.ASCII.GetBytes(packet);

// Отправка пакетов в серверное приложение на порт 5000

Client.Send(data, data.Length, "localhost", 5000);

displayTextBox += "\r\nПакет отослан\r\n";

inputTextBox.Clear();

}

}

public void WaitForPackets()

{

while(true)

{

// Получение массива байтов от сервера

byte[] data = client.Receive(ref receivePoint);

// Вывод пакета данных в текстовое поле

displayTextBox.Text += "\r\nПакет принят:" +

"\r\nДлина: + data.Length + "\r\nСодержащий: " +

System.Text.Encoding.ASCII.GetString(data) + "\r\n";

}

}

}

Класс клиента работает почти также, за исключением того, что объект клиента отправляет пакеты только при вводе пользователем сообщения в текстовое поле TextBox и нажатии на клавишу < Enter >. При выполнении этих условий вызывается обработчик события inputTextBox_KeyDown(). В этом обработчике вначале строка, введенная пользователем в текстовое поле, преобразуется в массив байтов. После чего, для отправки массива в серверное приложение, размещенное на localhost (то есть на тоже самой машине), вызывается метод UdpClient.Send (). При этом указывается номер порта – 5000, известный как номер приложения сервера.

Следует отметить, что в конструкторе клиента создается объект клиента для получения пакетов на порт 5001 от сервера. Этот порт выбран потому, что сервер уже занял порт с номером 5000. В методе Client. WaitForPackets() также используется бесконечный цикл, ожидающий поступления пакетов данных от сервера. При этом метод UdpClient.Receive () блокируется (методом UdpClient.Send ()) до окончания процесса получения пакетов информации. Поскольку методом Client. WaitForPackets() управляет отдельный поток, то блокирование работы одной функции не влияет на выполнение сервером другой работы, например, обработки введенных пользователем данных.

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

1.6. Пример многопоточного взаимодействия между приложениями

Программа состоит из приложения сервера и двух приложений клиентов. Приложение сервера позволяет приложению клиента подключиться к серверу и играть в известную игру "крестики – нолики". При соединении клиента с сервером создается экземпляр класса Player для обслуживания клиента в отдельном потоке управления. Это позволяет серверу управлять запросами обоих клиентов. Сервер присваивает значение " Х " первому клиенту, осуществившему соединение. Это означает, что игрок Х осуществил первый ход. Затем он присваивает значение "0" второму клиенту. По ходу игры сервер поддерживает информацию независимо от состояния игрового поля так, чтобы соблюдались правила выполнения ходов, запрошенных игроками. Однако, ни сервер, ни клиент не могут определить победу игроков, потому что в данной программе метод GameOver () всегда возвращает false. Приложение каждого клиента поддерживает свою версию интерфейса игрового поля "крестиков-ноликов". Игрок может ставить кресты или нули только на пустые клетки поля. Класс Square используется для описания клеток игрового поля.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: