Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Литвинов / Лабораторна робота 1.RC1.print.docx
Скачиваний:
26
Добавлен:
23.03.2015
Размер:
262.37 Кб
Скачать

1.3 Udp

Як вже було вказано, протокол UDP не вимагає зєднання – данні можуть бути надіслані не одному, а множині отримувачів використовуючи при цьому один сокет.

Для огранизації взаємодії використовується класс System.Net.Sockets.UdpClient в конструктор якого передається адреса віддаленого хоста та номер порту у разі клієнтського додатку, або номер порта в разі серверного.

UdpClient udpc = new UdpClient(2055);

Та

string hostName = Dns.GetHostName();

IPAddress[] ipHostAddressList = Dns.Resolve(hostName).AddressList;

IPAddress ipServerAddress = ipHostAddressList[0];

UdpClient udpc = new UdpClient(ipServerAddress.ToString(), 2055);

Отримання даних здійснюється з використанням методу Receive:

IPEndPoint ep = null;

byte[] data = udpc.Receive(ref ep);

де

data – байтовий масив, в який зберігаються отримані дані

ep – адреса відправника.

Відправка даних здійснюється з використанням методу Send.

Якщо адреса віддаленого хоста була задана в конструкторі використовується

виклик методу

udpc.Send(sdata, sdata.Length);

де

data – байтовий масив

Інакше, в метод передається адреса процесу отримувача

udpc.Send(sdata, sdata.Length, ep);

де

IPEndPoint ep – адреса отричувача.

Розглянемо задачу віддаленої ідентифікації користувача.

Серверна програма має вигляд.

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

namespace SocketTest

{

public class UDPServer

{

public void Run()

{

UdpClient udpc = new UdpClient(2055);

Console.WriteLine("Server started on port 2055");

IPEndPoint ep = null;

string PID;

string status = "not identified";

while (true)

{

byte[] rdata = udpc.Receive(ref ep);

PID = Encoding.ASCII.GetString(rdata);

//Some logic to identify

if (PID == "12345")

status = "identified";

byte[] sdata = Encoding.ASCII.GetBytes(status);

udpc.Send(sdata, sdata.Length, ep);

}

}

}

}

Клієнтська програма.

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

namespace SocketTest

{

public class UDPClient

{

public void Run()

{

string hostName = Dns.GetHostName();

IPAddress[] ipHostAddressList = Dns.Resolve(hostName).AddressList;

IPAddress ipServerAddress = ipHostAddressList[0];

UdpClient udpc = new UdpClient(ipServerAddress.ToString(), 2055);

IPEndPoint ep = null;

while (true)

{

Console.Write("Enter your personal identifier: ");

string PID = Console.ReadLine();

if (PID == "" )

{

//Console.Write("Press ESC to quit. ");

break;

}

//

byte[] sdata = Encoding.ASCII.GetBytes(PID);

udpc.Send(sdata, sdata.Length);

byte[] rdata = udpc.Receive(ref ep);

string status = Encoding.ASCII.GetString(rdata);

Console.WriteLine(status);

if (status == "identified")

{

break;

}

}

}

}

}

Тестова програма має вигляд.

private static UDPServer udpserver = new UDPServer();

private static UDPClient udpclient = new UDPClient();

static void Main(string[] args)

{

Thread serverThread = new Thread(startUDPServer);

serverThread.IsBackground = true;

serverThread.Start();

Console.WriteLine("Press ENTER to test interaction...");

if (Console.ReadKey().Key == ConsoleKey.Enter) ;

{

udpclient.Run();

}

}

private static void startUDPServer()

{

udpserver.Run();

}

Результати тесту показан на рис.

Рис.

Розглянемо приклад посилки однієї датаграми декільком отримувачам. Для цього отправувач відправляє пакети на адресу в діапазоні 224.0.0.1 - 239.255.255.255(Class D address group). Отримувачі можуть увійти в цю групу (join the group) та почати отримувати пакети. Вход в групу здійснюється методом JoinMulticastGroup(addr).

Розглянемо приклад публікації цін на товар «product» сервером, що здійснюється кожні 5 секунд. Для цього на адресу 230.0.0.1 відправляється датаграма, яку отримуєть клієнти, що входять у групу.

Код сервера

public class UDPPublisher

{

private string product = "Product";

public void Run()

{

UdpClient publisher = new UdpClient("230.0.0.1",8899);

Console.WriteLine("Publishing stock prices to 230.0.0.1:8899");

Random gen = new Random();

while(true)

{

double price = 400*gen.NextDouble()+100;

string msg = String.Format("{0} {1:#.00}",product,price);

byte[] sdata = Encoding.ASCII.GetBytes(msg);

publisher.Send(sdata,sdata.Length);

System.Threading.Thread.Sleep(5000);

}

}

}

Код клієнта

class UDPSubscriber

{

public void Run()

{

UdpClient subscriber = new UdpClient(8899);

IPAddress addr = IPAddress.Parse("230.0.0.1");

subscriber.JoinMulticastGroup(addr);

IPEndPoint ep = null;

for(int i=0; i<10;i++){

byte[] pdata = subscriber.Receive(ref ep);

string price = Encoding.ASCII.GetString(pdata);

Console.WriteLine(price);

System.Threading.Thread.Sleep(3000);

}

subscriber.DropMulticastGroup(addr);

}

}

Код тестера

private static UDPPublisher udppublisher = new UDPPublisher();

private static UDPSubscriber udpsubscriber = new UDPSubscriber();

static void Main(string[] args)

{

Thread serverThread = new Thread(startUDPPublisher);

serverThread.IsBackground = true;

serverThread.Start();

Console.WriteLine("Press ENTER to test interaction...");

if (Console.ReadKey().Key == ConsoleKey.Enter) ;

{

udpsubscriber.Run();

Console.WriteLine("Press ESC to exit");

while (true)

{

if (Console.ReadKey().Key == ConsoleKey.Escape)

{

break;

}

}

}

}

private static void startUDPPublisher()

{

udppublisher.Run();

}

Результат

Рис.

Завдання

На мінімальний бал:

1.Реалізувати всі приклади, що наведені в лабораторній роботі. Пояснити особливості описаних протоколів, варіантів організації взаємодії за допомогою сокетів.

Іншим:

  1. До наведених варіантів «асинхронних» серверів написати варіанти асинхронних клієнтів.

  2. Здійснити серверну обробку потоку сирих даних (потоку байтів) що поступають від клієнтів зі зберіганням їх в базі даних. Наприклад, існує множина пристроїв, кожен з яких раз в мінуту передає потік посекундних двобайтних значень певних характеристик. Організувати паралельну обробку. Обробити варіанти втрати зв’язку, невиходу в означений термін (здійснення прийому інформації з попередніх сеансів).

  3. Реалізувати версію системи публікації-подписки цін на товари. Декілька серверів публікують свої ціни на товари, клієнти отримують ці ціни, виконують порівняння та виводять в GUI-інтерфейс користувача порівняльну по вказаному товару. Здійснити прийом(зберігання та відображення) цін з інтервалом визначеним користувачем.

  4. Написати простішу програму чат на базі архітектури «клієнт-сервер» з використанням вивчених технологій.