Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Создание сокета и байтовых массивов
Откройте новое окно, выбрав пункт в «Обозревателе решений». Для создания дескриптора сокета можно использовать строку кода: System.Net.Sockets.Socket clientSocket; Запись упрощается, если применить директиву using к пространству имен System.Net.Sockets: Socket clientSocket; Поэтому сразу после директивы using System.Windows.Forms; в блок директив необходимо дописать две дополнительные строчки кода: using System.Net.Sockets; using System.Net; Это позволит вызывать методы для работы с сокетом в более короткой форме. Для корректной работы клиента необходимо создать один дескриптор сокета, два байтовых массива и одну булеву переменную. Они объявляются в файле Form1.cs в области видимости класса Form1, то есть между открывающейся фигурной скобкой после строки public partial class Form1 : Form и соответствующей закрывающейся скобкой: Socket clientSocket; bool isClientSocketClosed = true; byte[] byteDataRecv = new byte[1024]; byte[] byteDataSend = new byte[1024]; Дескриптор сокета clientSocket еще не определяет тип сокета и тип используемого протокола, то есть сам сокет пока что не существует. Булева переменная isClientSocketClosed принимает значение true, если сокет не существует, то есть закрыт, и значение false, если сокет создан и работает. Байтовый массив byteDataRecv имеет размер 1024 байта и используется для считывания принимаемой клиентом информации. Байтовый массив byteDataSend имеет тот же размер и используется клиентом для подготовки информации для дальнейшей передачи по сети. VS автоматически проверяет корректность вашего кода. Для получения подробной информации об ошибках наведите курсор на подчёркнутый текст. Метод ClientStart() Пользователь должен иметь возможность включать и выключать клиентское приложение. Для этого необходимо реализовать методы запуска и остановки работы клиента. Для запуска клиента мы будем использовать закрытый метод ClientStart(): private void ClientStart() { try { clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); IPAddress ipAddress; if (!IPAddress.TryParse(textBox1.Text, out ipAddress)) ipAddress = IPAddress.Parse("127.0.0.1"); Int32 port; if (!Int32.TryParse(textBox2.Text, out port)) port = 40001; EndPoint epClient = (EndPoint)new IPEndPoint(ipAddress, port); clientSocket.Bind(epClient); EndPoint epSender = (EndPoint)new IPEndPoint(IPAddress.Any, 0); clientSocket.BeginReceiveFrom(byteDataRecv, 0, byteDataRecv.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveCallback), null); textBox6.Text = "Клиент запущен (" + epClient.ToString() + ")"; button1.Text = "Стоп"; button2.Enabled = true; isClientSocketClosed = false; } catch (Exception ex) { textBox6.Text = "При создании сокета возникла ошибка"; MessageBox.Show(ex.Message, "Клиент времени и даты", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Исполняемый код помещен в блок try, а обработка возможных ошибок в блок catch. С помощью оператора создается дейтаграммный сокет, работающий по протоколу UDP. Сокету должна соответствовать пара из IP-адреса и порта, которая называется EndPoint (или IPEndPoint). Значения задаются полями Text элементов textBox1и textBox2 с помощью метода TryParse. Если этот метод возвращает false, то выбираются значения по-умолчанию. Созданный объект epClient привязывается к сокету с помощью метода Bind. Создается дополнительный объект epSender для фиксирования IP-адреса и порта другой стороны передачи. Сокет устанавливается в режим асинхронного приема в отдельном потоке с помощью метода BeginReceiveFrom. Метод ReceiveCallback() Каждый принятая дейтаграмма будет вызывать срабатывание метода ReceiveCallback(): private void ReceiveCallback(IAsyncResult ar) { try { EndPoint epSender = (EndPoint)new IPEndPoint(IPAddress.Any, 0); int bytesRead = clientSocket.EndReceiveFrom(ar, ref epSender); if (bytesRead > 0) { string stringRead = Encoding.UTF8.GetString(byteDataRecv, 0, bytesRead); MessageBox.Show(Form1.ActiveForm, "Сообщение '" + stringRead + "' длиной " + bytesRead.ToString() + " принято от сервера времени и даты " + epSender.ToString(), "Время и дата", MessageBoxButtons.OK, MessageBoxIcon.Information); Array.Clear(byteDataRecv, 0, bytesRead); clientSocket.BeginReceiveFrom(byteDataRecv, 0, byteDataRecv.Length, SocketFlags.None, ref epSender, new AsyncCallback(ReceiveCallback), null); } } catch (ObjectDisposedException) { if (isClientSocketClosed) return; } catch (Exception ex) { MessageBox.Show(ex.Message, "Клиент времени и даты", MessageBoxButtons.OK, MessageBoxIcon.Error); } } В результате работы метода EndReceiveFrom в целочисленную переменную bytesRead записывается количество принятых байтов информации, а в epSender – IP-адрес и порт отправителя. Само сообщение хранится в байтовом массиве byteDataRecv. Если сообщение было принято, то его содержание и отправитель выводятся в информационном окне. Байтовый массив очищается методом Array.Clear, а сокет опять устанавливается в режим асинхронного приема. Метод ClientStop() Для завершения работы с сокетом используется метод ClientStop(): private void ClientStop() { try { if (!isClientSocketClosed) { clientSocket.Close(); button1.Text = "Старт"; button2.Enabled = false; textBox6.Text = "Работа клиента прекращена"; isClientSocketClosed = true; } } catch (Exception ex) { MessageBox.Show(ex.Message, "Клиент времени и даты", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Закрытие сокета должно сопровождаться установлением булевой переменной в состояние true. Событие Click Используем кнопку button1 для вызова методов ClientStart() и ClientStop(). В окне «Обозреватель решений» двойным щелчком по пункту откроем окно «Конструктор». Двойным щелчком по кнопке button1 автоматически создадим обработчик события, вызываемый в программе при нажатии пользователем этой кнопки. Добавим в тело метода вызов ClientStart() и ClientStop(): private void button1_Click(object sender, EventArgs e) { if (isClientSocketClosed) ClientStart(); else ClientStop(); } В дальнейшем мы еще не раз воспользуемся этим приемом для привязки методов к событиям. Метод Send() Для отправки сообщений будет использоваться метод Send(): private void Send() { try { IPAddress ipAddress; if (!IPAddress.TryParse(textBox4.Text, out ipAddress)) ipAddress = IPAddress.Parse("127.0.0.1"); Int32 port; if (!Int32.TryParse(textBox5.Text, out port)) port = 40000; EndPoint epServer = new IPEndPoint(ipAddress, port); byteDataSend = System.Text.Encoding.UTF8.GetBytes(textBox3.Text); clientSocket.BeginSendTo(byteDataSend, 0, byteDataSend.Length, SocketFlags.None, epServer, new AsyncCallback(SendCallback), null); textBox6.Text = "Сообщение '" + textBox3.Text + "' отправлено " + epServer.ToString(); } catch (ObjectDisposedException) { if (isClientSocketClosed) return; } catch (Exception ex) { MessageBox.Show(ex.Message, "Клиент времени и даты", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Таким образом, отправляемое сообщение помещается в байтовый массив byteDataSend и отправляется асинхронным методом BeginSendTo в отдельном потоке по IP-адресу и порту, полученным из полей Text элементов textBox4 и textBox5 и записанным в объект epServer. Метод SendCallback() При окончании отправки вызывается метод SendCallback(): private void SendCallback(IAsyncResult ar) { try { clientSocket.EndSend(ar); } catch (Exception ex) { MessageBox.Show(ex.Message, "Клиент времени и даты", MessageBoxButtons.OK, MessageBoxIcon.Error); } } Самостоятельно привяжите метод Send() к нажатию кнопки button2. |
Последнее изменение этой страницы: 2019-03-22; Просмотров: 233; Нарушение авторского права страницы