Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции по ая.docx
Скачиваний:
22
Добавлен:
20.09.2019
Размер:
276.66 Кб
Скачать

Создание простого клиент-серверного приложения используя сокеты

У нас будут два различных приложения, приложение Сервер и приложение Клиент. Приложение Сервер будет соединяться с портом и в режиме прослушивания ожидать подключения Клиента. Как только Клиент подсоединиться он пошлет тестовое сообщение Серверу. Этот текст затем будет отображен в консоли приложения Сервера.

Вот исходный код приложения Сервера.

using System;

using System.Text;

using System.Net;

using System.Net.Sockets;

using System.IO;

class SocketServer

{

public static void Main()

{

StreamWriter streamWriter;

StreamReader streamReader;

NetworkStream networkStream;

TcpListener tcpListener = new TcpListener(5555);

tcpListener.Start();

Console.WriteLine("The Server has started on port 5555");

Socket serverSocket = tcpListener.AcceptSocket();

try

{

if (serverSocket.Connected)

{

while (true)

{

Console.WriteLine("Client connected");

networkStream = new NetworkStream(serverSocket);

streamWriter = new StreamWriter(networkStream);

streamReader = new StreamReader(networkStream);

Console.WriteLine(streamReader.ReadLine());

}

}

if (serverSocket.Connected)

serverSocket.Close();

Console.Read();

}

catch (SocketException ex)

{

Console.WriteLine(ex);

}

}

}

Приложение сервер стартует на порте 5555, отображает соответствующее сообщение и ждет входящего запроса на подсоединение от Клиента. Как только Клиент устанавливает соединение на тот же порт, сообщение "Client connected" отображается на консоли.

Рассмотрим на исходный код приложения Клиента, который будет подсоединяться к приложению Сервера используя тот же порт т.е. 5555.

using System;

using System.Text;

using System.Net;

using System.Net.Sockets;

using System.IO;

class SocketClient

{

static void Main(string[] args)

{

TcpClient tcpClient;

NetworkStream networkStream;

StreamReader streamReader;

StreamWriter streamWriter;

try

{

tcpClient = new TcpClient("localhost", 5555);

networkStream = tcpClient.GetStream();

streamReader = new StreamReader(networkStream);

streamWriter = new StreamWriter(networkStream);

streamWriter.WriteLine("Message from the Client...");

streamWriter.Flush();

}

catch (SocketException ex)

{

Console.WriteLine(ex);

}

Console.Read();

}

}

И в клиенте и в сервере используются потоки. Поток networkStream принимает или передает данные из сети или в сеть. Данный поток ассоциируется с потоком streamReader или streamWriter для получения или передачи сообщений по сети.

Многопоточность

C# поддерживает параллельное выполнение кода через многопоточность. Поток – это независимый путь исполнения, способный выполняться одновременно с другими потоками.

Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой (“главный” поток), и становится многопоточной при помощи создания дополнительных потоков. Многопоточность позволяет приложениям разделять задачи и работать над каждой независимо/

Многозадачность - это одновременное исполнение нескольких потоков. Существует два вида многозадачности — совместная (cooperative) и вытесняющая (preemptive). Совместная - каждый поток отвечает за возврат управления процессору, чтобы тот смог обработать другие потоки. Вытесняющая - процессор отвечает за выдачу каждому потоку определенного количества времени, в течение которого поток может выполняться, — кванта времени (timeslice). Далее процессор переключается между разными потоками, выдавая каждому потоку его квант времени, а программист может не заботится о том, как и когда возвращать управление, в результате чего могут работать и другие потоки.

Для работы с многопоточностью среда .NET предоставляет пространство имен System.Threading. В данном пространстве имен содержится огромное количество различных типов, наиболее важны из них класс Thread. У данного класса есть много методов и свойств, например:

Start() - начинает выполнение потока

Suspend() - приостанавливает поток

Resume() - восстанавливает работу потока

Priority - свойство определяющие приоритет потока

Разработаем простейшее многопоточное приложение, в котором каждый из потоков выводит на консоль свое сообщение.

using System;

using System.Threading;

class ThreadTest

{

static void Main()

{

Thread t = new Thread(WriteY);

t.Start();

while (true)

Console.Write("x");

}

static void WriteY()

{

while (true)

Console.Write("y");

}

}

Создадим метод WriteY, который выводит на экран букву «у». В методе Main, создадим поток связанный с методом WriteY, и запустим его при помощи метода Start. После этого в вечном цикле будем выводить на экран букву «x». Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой (“главный” поток), и становится многопоточной при помощи создания дополнительных потоков.

CLR назначает каждому потоку свой стек, так что локальные переменные хранятся раздельно. В следующем примере мы определяем метод с локальной переменной, а затем выполняем его одновременно в главном и во вновь созданном потоках:

static void Main()

{

new Thread(Go).Start();

Go();

Console.ReadLine();

}

static void Go()

{

for (int cycles = 0; cycles < 200; cycles++)

Console.WriteLine("cycles: {0}",cycles);

}

Отдельный экземпляр переменной cycles создается в стеке каждого потока, так что выводится свое собственное значение для каждого потока.

Управление многопоточностью осуществляет планировщик потоков, эту функцию CLR обычно делегирует операционной системе. Планировщик потоков гарантирует, что активным потокам выделяется соответствующее время на выполнение, а потоки, ожидающие или блокированные, не потребляют времени CPU.

На однопроцессорных компьютерах планировщик потоков использует квантование времени – быстрое переключение между выполнением каждого из активных потоков.

На многопроцессорных компьютерах многопоточность реализована как смесь квантования времени и подлинного параллелизма, когда разные потоки выполняют код на разных CPU. Необходимость квантования времени все равно остается, так как операционная система должна обслуживать как свои собственные потоки, так и потоки других приложений.

Типовое приложение с многопоточностью выполняет длительные вычисления в фоновом режиме. Главный поток продолжает выполнение, в то время как рабочий поток выполняет фоновую задачу. В приложениях Windows Forms, когда главный поток занят длительными вычислениями, он не может обрабатывать сообщения клавиатуры и мыши, и приложение перестает откликаться. По этой причине следует запускать отнимающие много времени задачи в рабочем потоке.

Другое применение многопоточность находит в методах, выполняющих интенсивные вычисления. Такие методы могут выполняться быстрее на многопроцессорных компьютерах, если рабочая нагрузка разнесена по нескольким потокам.

Многопоточность наряду с достоинствами имеет и свои недостатки. Самое главный из них – значительное увеличение сложности программ. Сложность увеличивают не дополнительные потоки сами по себе, а необходимость организации их взаимодействия. Кроме того, чрезмерное использование многопоточности отнимает ресурсы и время CPU на создание потоков и переключение между потоками.