Низкоуровневые операции в ИС. Сокеты в C#
Понятие сокета Если требуется получить доступ к сетевым операциям низкого уровня, в программе следует использовать класс Socket. Протокол TCP/IP (базовый протокол сети Internet) основывается на соединениях, устанавливаемых между двумя компьютерами, обычно называемых клиентом и сервером. Множество приложений для Internet базируются на использовании протокола TCP/IP. Протокол TCP/IP построен на основе использования сетевых соединений – соединение сначала должно быть установлено, затем осуществляется передача данных, после чего оно разрывается.
Понятие сокета Сокеты TCP являются важным понятием в программировании. С их помощью разработчик может создавать свои прикладные протоколы, отличные от HTTP и FTP. Сокеты (socket) – это описатель сетевого соединения с другим приложением. Сокет TCP использует протокол TCP, наследуя все свойства этого протокола. Для создания TCP необходима следующая информация: IP-адрес локальной машины; Номер порта TCP, который использует приложение на локальной машине; IP-адрес машины, с которой устанавливается связь; Номер порта TCP, на который отзывается приложение, ожидающее установления связи.
Сокеты в C# Язык C# поддерживает два типа сетевых соединений: серверные, реализуемые с помощью объектов класса TcpListener; клиентские, реализуемые с помощью объектов класса TcpClient.
Программа - сервер Программа – сервер выполняет следующие шаги: Ожидание подключения клиента; Установка соединения с клиентом; Отправка/получение от клиента сообщения; Разрыв соединения и завершение программы.
Программа-сервер Необходимо понимать, что серверные приложения запускаются на локальном компьютере. В качестве параметра конструктор класса TcpListener принимается номер порта, который впоследствии и будет прослушиваться программой. Однако объект класса TcpListener позволяет только прослушивать определенный порт компьютера. Любые процессы передачи данных через этот сокет осуществляются с использованием объекта TcpClient. Ообъект TcpClient возвращается методом AcceptTcpClient() класса TcpListener, что обеспечивает сам процесс прослушивания порта.
Сервер При создании серверного приложения следует подключить модули: using System.Net; using System.Net.Sockets; Затем использовать класс TcpListener. Объекты этого класса связываются с заданным портом. Int32 port = 13000; IPAddress localAddr = IPAddress.Parse(" "); TcpListener server = new TcpListener(localAddr, port); server.Start();
Сервер После связывания программы с портом с помощью вызова метода AcceptTcpClient() можно подключиться к этому порту и начать прослушивание входящих соединений: TcpClient client = server.AcceptTcpClient(); После подключения создается поток входных/выходных сообщений: NetworkStream stream = client.GetStream();
Чтение сообщений Через сокет передается массив байт, который после получения нужно преобразовать в строку. Byte[] bytes = new Byte[256]; String data = null; int i = stream.Read(bytes, 0, bytes.Length); data=System.Text.Encoding.UTF8. GetString(bytes, 0, i);
Отправка сообщений Перед отправкой через сокет строку необходимо преобразовать в массив байт. Byte[] bytes = new Byte[256]; String data = text; bytes =System.Text.Encoding.UTF. GetBytes(data); stream.Write(bytes, 0, bytes.Length);
Фрагмент программы-сервера try { Int32 port = 13200; IPAddress localAddr = IPAddress.Parse(" "); //создание и запуск сервера TcpListener server = new TcpListener(localAddr, port); server.Start(); Byte[] bytes = new Byte[256]; String data = null;
Фрагмент программы-сервера while(true) { //прослушивание порта и ожидание подключения TcpClient client = server.AcceptTcpClient(); data = null; //произошло подключение, создается поток сообщений NetworkStream stream = client.GetStream();
Фрагмент программы-сервера // чтение сообщения int i = stream.Read(bytes, 0, bytes.Length); data = System.Text.Encoding.UTF8.GetString(bytes, 0, i); //преобразование данных data = data.ToUpper(); //отправка сообщения byte[] msg = System.Text.Encoding.UTF8.GetBytes(data); stream.Write(msg, 0, msg.Length);
Фрагмент программы-сервера //завершение работы с потоком сообщений client.Close(); }//end while }// end try catch(SocketException ex) { // ошибки соединения }
Программа-клиент Программа-клиент выполняет следующие действия: Подключение к серверу. Отправка/получение сообщения от сервера. Отображение полученного сообщения пользователю. Разрыв соединения с сервером.
Программа-клиент Для подключения к серверу используется конструктор, параметрами которого служат IP-адрес серверной программы и порт, который сервер прослушивает: TcpClient client = new TcpClient(server, port); Затем, после подключения к серверу, аналогично серверной программе, создается поток входных/выходных сообщений: NetworkStream stream = client.GetStream();
Программа-клиент Можно отправить сообщение серверу, предварительно преобразовав строку в массив байт: Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(message); stream.Write(bytes, 0, bytes.Length); Или получить сообщение от сервера, преобразовав массив байт в строку: bytes = new Byte[256]; String responseData = String.Empty; Int32 i = stream.Read(bytes, 0, bytes.Length); responseData = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Фрагмент программы-клиента void Connect(String server, String message, Int32 port) { try { // Подключение к серверу TcpClient client = new TcpClient(server, port); // Создание потока сообщений NetworkStream stream = client.GetStream(); // Отправка сообщения Byte[] bytes = System.Text.Encoding.ASCII.GetBytes(message); stream.Write(bytes, 0, bytes.Length);
Фрагмент программы-клиента bytes = new Byte[256]; String responseData = String.Empty; // получение сообщения Int32 i = stream.Read(bytes, 0, bytes.Length); responseData = System.Text.Encoding.UTF8.GetString(bytes, 0, i); client.Close(); } catch (Exception e) { // ошибка соединения } }// end connection
Фрагмент программы-клиента Пример соединения с программой- сервером. Connect(localhost,text,13000); Connect( ,text,13200);
Подключение к БД в программе- сервере try { this.odbcConnection1.Open(); // использование полученного от клиента сообщения в качестве параметра запроса this.odbcCommand1.Parameters["p1"].Value=data; rdr=this.odbcCommand1.ExecuteReader(); } catch(Exception exx) { … }
Подключение к БД в программе- сервере while(rdr.Read()) // подсчет количества записей {rw++; } rdr.Close(); data=rw.ToString(); // отправка клиенту количества записей byte[] msg = System.Text.Encoding.ASCII.GetBytes(data); stream.Write(msg, 0, msg.Length); rdr=this.odbcCommand1.ExecuteReader(); data=result;
//определение количества полей в записи data=rdr.FieldCount.ToString(); // отправка клиенту количества полей в записи msg = System.Text.Encoding.ASCII.GetBytes(data); stream.Write(msg, 0, msg.Length);
Отправка клиенту результата запроса while (rdr.Read()) { data=rdr["tovar"].ToString(); msg = System.Text.Encoding.ASCII.GetBytes(data); stream.Write(msg, 0, msg.Length); data=rdr["tip"].ToString(); msg = System.Text.Encoding.ASCII.GetBytes(data); stream.Write(msg, 0, msg.Length); }
Получение результата в программе клиента //Получение от сервера числа записей Byte[] data2 = new Byte[256]; Int32 bytes2 = stream.Read(data2, 0, data2.Length); int rw= Convert.ToInt32(System.Text.Encoding.ASCII.GetString( data2, 0, bytes2)); // Получение от сервера количества полей в записи Byte[] data1 = new Byte[256]; Int32 bytes1 = stream.Read(data1, 0, data1.Length); int col= Convert.ToInt32(System.Text.Encoding.ASCII.GetString( data1, 0, bytes1));
// Получение от сервера набора данных for (int j=1;j
Отображение данных в программе-клиенте Connect(this.textBox2.Text,this.textBox1. Text,13000); Connect(this.textBox2.Text,this.textBox1. Text,13200); this.dataGrid1.SetDataBinding( this.dataSet1,"Table1");