Протокол согласования учебной программы
по изучаемой учебной дисциплине
С ДРУГИМИ ДИСЦИПЛИНАМИ СПЕЦИАЛЬНОСТИ
Протокол согласования рабочей программы
с другими дисциплинами специальности
Название дисциплин | Кафедры, обеспечивающие преподавание данных дисциплин | Предложение об их изменении | Протокол |
Проектирование систем обработки данных | ИТАС | - | - |
Объектно-ориентированное проектирование и программирование | ИТАС | - | - |
Зав. кафедрой В.C. Муха
Дополнения и изменения в рабочей программе
На 2010/2011 год
Дополнений и изменений нет
РАБОЧАЯ ПРОГРАММА КУРСА
КОНСПЕКТ ЛЕКЦИЙ
ЛИТЕРАТУРА
ИНДИВИДУАЛЬНЫЕ ПРАКТИЧЕСКИЕ РАБОТЫ
КОНТРОЛЬНАЯ РАБОТА
КОНТРОЛЬ ЗНАНИЙ
МЕТОДИЧЕСКИЕ УКАЗАНИЯ ПО КУРСОВОМУ ПРОЕКТУ
Теоретический раздел
СОВРЕМЕННЫЕ СИСТЕМЫ ПРОГРАММИРОВАНИЯ
(часть I I)
(конспект лекций для студентов специальности 1-53 01 02 «Автоматизированные системы обработки информации»)
ЛЕКЦИЯ 1 (2 час.). ВВОДНАЯ ЛЕКЦИЯ.
ЛЕКЦИЯ 2 (4 час). СОЗДАНИЕ СЕТЕВЫХ ПРИЛОЖЕНИЙ НА ОСНОВЕ СОКЕТОВ TCP
ЛЕКЦИЯ 3 (4час). РАБОТА НА ОСНОВЕ ПРОТОКОЛА UDP
ЛЕКЦИЯ 4 (4 час). РАБОТА НА ОСНОВЕ ПРОТОКОЛА HTTP
ЛЕКЦИЯ 5 (4 час). РАБОТА С XML-ДОКУМЕНТАМИ
ЛЕКЦИЯ 6 (4 час). ЭЛЕКТРОННАЯ ПОЧТА
ЛЕКЦИЯ 7 (4 час). КРИПТОГРАФИЯ В NET
ЛЕКЦИЯ 8 (4 час). СОЗДАНИЕ ASP.NET-СЦЕНАРИЕВ
ЛЕКЦИЯ 9 (4час). ЭЛЕМЕНТЫ УПРАВЛЕНИЯ AJAX В ASP.NET-СЦЕНАРИЯХ
ЛЕКЦИЯ 10 (4 час). WEB-СЕРВИСЫ
ЛЕКЦИЯ 11 (6 час). РАЗРАБОТКА ОФИСНЫХ БИЗНЕС ПРИЛОЖЕНИЙ
ЛЕКЦИЯ 12 (4 час). ОСНОВЫ WINDOWS PRESENTATION FOUNDATION.
ТЕОРЕТИЧЕСКИЙ РАЗДЕЛ
РАЗДЕЛ 4. СЕТЕВОЕ ПРОГРАММИРОВАНИЕ В NET
ЛЕКЦИЯ 1. ВВОДНАЯ ЛЕКЦИЯ.
предыдущий_раздел следующий_раздел следующая_лекция список лекций
Настоящий ЭУМК содержит существенные сведения по работе в сети, включая Интернет. Для понимания программ, представленных в этом пособии, большая часть из которых взята из источников [1,8] следует иметь некоторое общее представление о физической организации компьютерной сети, принципах ее аппаратной организации и используемых протоколах. В этой вводной лекции мы коротко ответим на эти волпросы.
Физически компьютерная сеть представляет группу компьютеров, соединенных каналами связи. Сети делятся на следующие категории:
ÿ Локальные (например, ETHERNET) – это сеть, размещенная на ограниченном участке;
ÿ Региональные (например, MAN – metropolitan area network) ;
ÿ Глобальные (WAN) – объединяет несколько LAN.
По типу передачи данных сети делятся на сети с коммутацией пакетов и сети с коммутацией каналов. При коммутации пакетов передаваемые данные делятся на блоки (пакеты), которые пересылаются независимо друг от друга. Передеча данных осуществляется в определенном формате, который называют протоколом. Известны разные протоколы, например CSMA/CD, Token Ring, TCP/IP, HTTP, SMTP и т.д. Обилие протоколов связано с различным характером передаваемой информации (гипертекст, бинарные файлы, электронная почта и т.д.).
Сетевая плата
Компьютер может работать в сети, если он оснащен сетевой платой. Сетевая плата (сетевой адаптер) – это схема, с помощью которой компьютер пожключается к линии связи. Сетевая плата имеет уникальный адрес, обеспечивающий обнаружение компьютера в сети и ждоставку ему информации.
Сетевой адрес компьютера можно узнать в окне DOS:
Ø ipconfig /all
Концетратор
Концентратор (хаб) – это устройство, предназначенное для подключения нескольких компьютеров к сети. Хаб имеет число портов от 4 до 24. Каждый компьютер подключается к собственному порту.
Коммутатор
Коммутатор (switch) разделяет сети на фрагменты. Это иллюстрируется следующей картинкой:
Маршрутизаторы
Маршрутизатор – это устройство, которое соединяет между собой различные подсети. Маршрутизатор хранит таблицу маршрутов с перечнем путей, по которым можно попасть в конкрентные сети. Местную таблицу маршрутов можно увидеть, если в Windows выдать команду
Ø route print
Чтобы увидеть весь маршрут доступа к удаленному хосту просто укажите
Ø tracert www.globalknowledge.com
Базовые протоколы
Сеть Интернет использует протокол IP (Internet Protocol). Этот протокол обеспечтивает связь двух узлов. Каждый узел идентифицируется 32-битным адресом, называемым IP-адресом. Данные в IP-протоколе предваряются заголовком. Заголовок содержит следующие поля:
ÿ Версия – 4 бита
ÿ Длина – 4 бита
ÿ Тип обслуживания – 1 байт
ÿ Общая длина сообщения – 2 байта
ÿ Идентификация – 2 байта (сообщение разбивается на фрагменты. Каждый фрагмент имеет один и тот же идентификатор);
ÿ Флаги – 3 бита (учитывают, фрагментировано ли сообщенрие и является ли этот фрагмент последним).
ÿ Смещение фрагмента – 13 битов
ÿ Время жизни сообщения – 1 байт
ÿ Протокол (тип информации) – 1 байт
ÿ Контрольная сумма – 2 байта
ÿ Адрес источника – 4 байта
ÿ Адрес назначения – 4 байта
ÿ Опции
IP адрес состоит из двух частей – сетевого адреса и адреса узла (хоста). Информация поступает в порт. Портов может быть много – порядка 64 тысяч. Порты используются на транспортном уровне обмена. Используемые порты можно увидеть по команде
Ø netstat –a
Эта команда выдает перечень всех используемых портов.
Протокол TCP (transmission control protocol) используется для передачи сообщений на транспортном уровне – в пределах одной локальной сети. Этот протокол требует, чтобы перед отправкой сообщения было открыто соединение. Серверное приложение пассивно ожидает запросы от клиентов. Клиентское приложение должно выполнить активное открытие соединения и послать запрос серверу. Сообщение протокола TCP имеет следующий формат:
Порт источника – 2 байта
Порт назначения – 2 байта
Номер пакета – 4 байта
Номер подтверждения – 4 байта
Смещение данных – 4 байта (информация о начале пакета данных)
Резерв – 6 байт
Размер приемного буфера – 2 байта
Контрольная сумма
Указатель срочности
Отметим, что ТСР является сравнительно медленным, но надежным протоколом.
Протокол UDP (user datagram protocol) в отличие от ТСР является быстрым протоколом. Однако его надежность при этом не столь высока, как у ТСР. UDP не требует открывать соединение. Данные можно передавать сразу по мере их готовности. Протокол UDP не требует подтверждения приема информации. Главное преимущество UDP – быстрая передача и широковощетельная (групповая) доставка. Сообщние в UDP – формате имеет следующую структуру:
Порт источника – 2 байта
Порт назначения – 2 байта
Длина сообщения – 2 байта
Контрольная сумма – 2 байта
Команда ping address позволяет отправить сообщение ЭВМ с указанным адресом. Пример
Ø ping 212.183.100.193
Ø ftp
ftp > open имя
Ø dir …
Ø get …
Ø bye
утилита >nslookup возвращает IP-адрес по заданному IP-имени.
WEB-proxy
WEB-proxy кэширует web-запросы клиентов. Например, WEB-Proxy может кэшировать web-запросы так, чтобы последующие web-запросы на те же страницы получали ответ не из сервера, а из кеша.
Работа с файлами
При работе в сети важное место уделяется вводу-выводу из файлов. Ниже помещен простой пример такой работы.
using System;
using System.IO;
using System.Text;
class SyncIO
{
public static void Main(String [] args)
{
FileStream syncF=new FileStream (“Demo.txt”, FileMode.OpenOrCreate);
byte [] writeBytes =Encoding.ASCII.GetBytes(“Hello,Friends”);
syncF.Write(writeBytes,0, writeBytes.Length);
byte [] readBuf = new byte[syncF.Length-1];
syncF.Seek(0,SeekOrigin.Begin);
syncF.Read(readBuf, 0,
(Convert.ToInt32(syncF.Length-1));
Console.WriteLine(“The content is:”+
Encoding.ASCII.GetString(readBuf));
}
}
Важный вариант ввода-вывода в файлы представляет асинхронный ввод-вывод. Этот вариант означает, что работа с файлом выполняется параллельно с инициировавшим его процессом. В качестве примера мы приведем следующий.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
namespace async2
{
class Program
{
static FileStream fileStm;
static byte[] readBuf;
static AsyncCallback CallBack;
static void Main(string[] args)
{
CallBack = new AsyncCallback(CallBackFunction);
fileStm = new FileStream(@"e:\CSharpProjects\myfile.txt",
FileMode.Open, FileAccess.Read, FileShare.Read, 64, true);
readBuf = new byte[fileStm.Length];
//call asynchronous reading
fileStm.BeginRead(readBuf, 0, readBuf.Length, CallBack, null);
// father the basic process imitating follows
for (int i = 0; i < 100; i++)
{
if (i % 9 == 0)
{
Console.WriteLine("Executes:"+i.ToString());
Thread.Sleep(10);
}
}
fileStm.Close();
Console.WriteLine("The main process stops");
Console.ReadLine();
}
static void CallBackFunction(IAsyncResult asyncResult)
{
Console.WriteLine("Well Done Fellow-programmer!");
Console.WriteLine(Encoding.ASCII.GetString(readBuf));
}
}
}
Операция асинхронного вывода определяется командой
fileStm = new FileStream(@"e:\CSharpProjects\myfile.txt",
FileMode.Open, FileAccess.Read, FileShare.Read, 64, true);
Именно, ее последним операндом – true. Операнд 64 – задает размер буфера ввода-вывода. После запуска ввода-вывода основно й процесс не тормозится а выполняется цикл:
for (int i = 0; i < 100; i++)
{
if (i % 9 == 0)
{
Console.WriteLine("Executes:"+i.ToString());
Thread.Sleep(10);
}
}
Когда ввод-вывод завершится, управление получит CallBack – функция:
static void CallBackFunction(IAsyncResult asyncResult)
Эта функция выдаст результат чтения (см. скриншот)
Если эту функцию изменить таким образом:
static void CallBackFunction(IAsyncResult asyncResult)
{
Thread.Sleep(100);
Console.WriteLine("Well Done Fellow-programmer!");
Console.WriteLine(Encoding.ASCII.GetString(readBuf));
}
то экран вывода изменится так (объясните, почему?)
ЛЕКЦИЯ 2. СОЗДАНИЕ СЕТЕВЫХ ПРИЛОЖЕНИЙ НА ОСНОВЕ СОКЕТОВ TCP
предыдущая лекция следующая лекция
Список лекций
Сокеты – это концевые точки соединения. Сокет состоит из порта и IP-адреса компьютера. Сокетное соединение устанавливается между двумя процессами, которые могут функционировать на одном и том же компьютере. Передача информации через сокет может быть двунаправленной (т.е. ориентироваться как на прием, так и на передачу).
Обычно сокетное приложение строится для приложений типа «клиент-сервер». Простое приложение этого типа помещено ниже. Сначала идет серверная часть, которая имеет следующий вид:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace ConsoleApplication1
{
class TCPServer
{
static void Main(string[] args)
{
try
{
IPAddress it = IPAddress.Parse("127.0.0.1");
TcpListener tclis = new TcpListener(it, 5002);
tclis.Start();
TcpClient tccli = tclis.AcceptTcpClient();
NetworkStream stm = tccli.GetStream();
byte[] readBuf =
new byte[256];
stm.Read(readBuf, 0, 256);
Console.WriteLine(Encoding.ASCII.GetString(readBuf));
stm.Close();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.ReadLine();
}
}
}
}
Теперь создадим приложение клиента (это отдельное приложение, для которого нужно создать новый проект). Приложение TCP-клиента имеет следующий вид.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace TCP_Client
{
class TCPClient
{
static void Main(string[] args)
{
try{
TcpClient cli = new TcpClient();
cli.Connect("localhost", 5002);
NetworkStream stm = cli.GetStream();
byte [] sendbytes =
Encoding.ASCII.GetBytes("Hello, fellow-programmer!!");
stm.Write(sendbytes, 0, sendbytes.Length);
cli.Close();
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Запускаем сначала приложение сервера, а затем – приложение клиента. Окно сервера отобразит переданную от клиента строку (рис.2.1):
Рис.2.1
Следующее приложение можно использовать для проверки открытых портов на сервере. Вот его текст
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace scanports
{
class myscan
{
static void Main(string[] args)
{
IPAddress addr = IPAddress.Parse("127.0.0.1");
for (int i = 1; i < 81; i++)
{
Console.WriteLine("Checking porrt {0}", i);
try
{
IPEndPoint endp = new IPEndPoint(addr, i);
Socket sk = new Socket(
AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
sk.Connect(endp);
Console.WriteLine("Port {0} is opened", i);
}
catch (SocketException se)
{
if (se.ErrorCode != 10061)
Console.WriteLine(se.Message);
}
}
}
}
}
Ниже помещен скриншот, демонстрирующий вывод программы. Видим, что порт 25 (используемый для электронной почты), открыт.
Рис.2.2
Интерес представляет также мультиплексный сервер, т.е. такой сервер, который одновременно может обслуживать несколько клиентов. Реализация подобного сервера иллюстрируется следующим программным листингом.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Threading;
using System.Collections;
using System.IO;
using System.Net.Sockets;
namespace multuserver
{
public class multiserv
{
public TcpClient cliSock;
public void runCli()
{
StreamReader stm = new StreamReader(cliSock.GetStream());
NetworkStream wrtStream = cliSock.GetStream();
string res = stm.ReadLine();
string s = res;
while (1 == 1)
{
res = stm.ReadLine();
if (res.IndexOf("END") >= 0)
{
Console.WriteLine("Cherio!");
break;
}
Console.WriteLine(s + " :" + res);
res += "\r\n";
byte[] dwrt = Encoding.ASCII.GetBytes(res);
wrtStream.Write(dwrt, 0, dwrt.Length);
}
cliSock.Close();
}
}
public class echo
{
const int ECHO_PRT = 8082;
public static int numClients = 0;
public static void Main(string[] args)
{
IPAddress ia = IPAddress.Parse("127.0.0.1");
try
{
TcpListener cliLis = new TcpListener(ia,ECHO_PRT);
cliLis.Start();
while (true)
{
TcpClient cli = cliLis.AcceptTcpClient();
multiserv chl = new multiserv();
chl.cliSock = cli;
Thread cliThread =
new Thread(new ThreadStart(chl.runCli));
cliThread.Start();
}
cliLis.Stop();
}
catch (Exception e)
{ }
}
}
}
Для связи с сервером пишем следующее клиентское приложение:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Collections;
namespace multi_client
{
public class mulCli
{
static void Main(string[] args)
{
Console.Write("Your Name, please:");
string usernm = Console.ReadLine();
Console.WriteLine("Connecting");
try
{
TcpClient cCli =
new TcpClient();
cCli.Connect("localhost", 8082);
StreamReader rdr = new StreamReader(cCli.GetStream());
NetworkStream nws = cCli.GetStream();
string dataToServer = usernm;
dataToServer += "\r\n";
byte[] data = Encoding.ASCII.GetBytes(dataToServer);
nws.Write(data, 0, data.Length);
while (1 == 1)
{
Console.WriteLine("New data, please:");
dataToServer = Console.ReadLine();
dataToServer += "\r\n";
data = Encoding.ASCII.GetBytes(dataToServer);
nws.Write(data, 0, data.Length);
if (dataToServer.IndexOf("END") >= 0)
break;
string returndata;
returndata = rdr.ReadLine();
//byte[] readBuf = new byte[256];
//nws.Read(readBuf,0,readBuf.Length);
// returndata = Encoding.UTF32.GetString(readBuf);
Console.WriteLine("Server answer is:" + returndata);
}
cCli.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
}
}
Создаем в отдельном проекте сервер, в отдельном – клиентскую часть. Запускаем сначала сервер, затем запускаем клиента. Ниже показан скриншот (рис.2.3), иллюстрирующий диалог между клиентом и сервером.
Рис.2.3
Дадим некоторый комментарий по программам клиента и сервера. Начнем с серверного приложения. Серверное приложение содержит потоковый класс
public class multiserv
{
public TcpClient cliSock;
public void runCli()
{
StreamReader stm = new StreamReader(cliSock.GetStream());
NetworkStream wrtStream = cliSock.GetStream();
string res = stm.ReadLine();
string s = res;
while (1 == 1)
{
res = stm.ReadLine();
if (res.IndexOf("END") >= 0)
{
Console.WriteLine("Cherio!");
break;
}
Console.WriteLine(s + " :" + res);
res += "\r\n";
byte[] dwrt = Encoding.ASCII.GetBytes(res);
wrtStream.Write(dwrt, 0, dwrt.Length);
}
cliSock.Close();
}
}
Единственным методом этого класса является метод public void runCli().
Именно в нем и реализуется связь с клиентом. Для чтения информации от клиента используется переменная StreamReader stm. Для передачи клиенту ответного сообщения используем переменную NetworkStream wrtStream. Порождение потока выполняется в другом классе серверного приложения (выделено жирным шрифтом):
while (true)
{
TcpClient cli = cliLis.AcceptTcpClient();
multiserv chl = new multiserv();
chl.cliSock = cli;
Thread cliThread =
new Thread(new ThreadStart(chl.runCli));
cliThread.Start();
}
Здесь создается новый поток и запускается метод runCli. Созданный поток сервера взаимодействует с одним клиентом (если клиентов несколько, каждого из них обслуживает свой собственный поток). Выход и завершение потока выполняется тогда, когда клиент вводит сообщение END.
Клиентское приложение строится на основе класса TcpClient. Переменная NetworkStream nws используется для передачи данных на сервер. Логика клиента во многом схожа слогикой сервера и не требует каких-либо подробных разъяснений.
Заключительный пример этой лекции демонстрирует использование низкоуровневых методов передачи – send и receive. Эти методы реализуются классом Socket. Найдите соответствующее место в программе. Остальные механизмы соответствуют ранее рассмотренным в этой лекции. Серверную часть мы реализуем таким образом:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace serv_2
{
public class serv
{
public static void Main()
{
try
{
IPAddress ipAd = IPAddress.Parse("127.0.0.1");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
TcpListener myList = new TcpListener(ipAd, 8001);
/* Start Listeneting at the specified port */
myList.Start();
Console.WriteLine("Порт сервера - 8001...");
Console.WriteLine("Концевая точка :" +
myList.LocalEndpoint);
Console.WriteLine("Сервер ожидает соединения.....");
Socket s = myList.AcceptSocket();
Console.WriteLine("Соединение установлено с " + s.RemoteEndPoint);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Принято от клиента...");
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(b[i]));
ASCIIEncoding asen = new ASCIIEncoding();
s.Send(asen.GetBytes("Полученная строка отправлена клиенту"));
Console.WriteLine("На этом все");
Console.ReadLine();
/* clean up */
s.Close();
myList.Stop();
}
catch (Exception e)
{
Console.WriteLine("Error..... " + e.StackTrace);
}
}
}
}
Клиентская часть имеет следующий вид:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
namespace client_2
{
public class clnt
{
public static void Main()
{
try
{
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Подключение.....");
tcpclnt.Connect("127.0.0.1", 8001);
// use the ipaddress as in the server program
Console.WriteLine("Связь с сервером установлена");
Console.Write("Введите строку для отсылки : ");
String str = Console.ReadLine();
Stream stm = tcpclnt.GetStream();
ASCIIEncoding asen = new ASCIIEncoding();
byte[] ba = asen.GetBytes(str);
Console.WriteLine("Передача.....");
stm.Write(ba, 0, ba.Length);
byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);
for (int i = 0; i < k; i++)
Console.Write(Convert.ToChar(bb[i]));
tcpclnt.Close();
}
catch (Exception e)
{
Console.WriteLine("Ошибка..... " + e.StackTrace);
}
}
}
}
Оконный интерфейс между сервером и клиентом показан на следующем скриншоте:
Таким образом, мы рассмотрели основные принципы TCP-взаимодействия. Были использованы две стороны – сторона клиента и сторона сервера. Базовым классом для реализации связи между ними выступил TcpListener. В следующей лекции рассматривается протокол UDP, который не ожидает подтверждения связи и выполняет передачу сразу («на лету»).
ЛЕКЦИЯ 3. РАБОТА НА ОСНОВЕ ПРОТОКОЛА UDP
предыдущая лекция следующая лекция
Список лекций
Протокол UDP реализует упрощенный вариант сетевого обмена между клиентом и сервером. Прежде всего, это упрощение связано с отстутствием подтверждения приема/передачи данных. Рассмотрим, как реализовать передачу сервером файла клиенту. Серверная часть имеет такой вид.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Sockets;
namespace udp_server
{
class FileSender
{
public static IPAddress remoteIPAdr;
public const int remotePort = 5012;
private static UdpClient sender = new UdpClient();
private static IPEndPoint endPoint;
private static FileStream fs;
static void Main(string[] args)
{
try
{
remoteIPAdr = IPAddress.Parse("127.0.0.1");
endPoint = new IPEndPoint(remoteIPAdr, remotePort);
fs=new FileStream(@"e:\work\my.html",
FileMode.Open,FileAccess.Read);
Thread.Sleep(200);
SendFile();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.ReadLine();
}
}
public static void SendFile()
{
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
try
{
sender.Send(bytes, bytes.Length, endPoint);
fs.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
Console.Read();
Console.WriteLine("OK");
}
}
}
Клиентская часть реализуется таким образом.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
namespace udp_client
{
class FileReceiver
{
private static int locport=5012;
private static UdpClient rudp=new UdpClient(locport);
private static IPEndPoint remoteept=
null;
private static FileStream fs;
private static byte[] rcbytes = new byte[0];
static void Main(string[] args)
{
ReceiveFile();
}
public static void ReceiveFile()
{
try
{
rcbytes = rudp.Receive(ref remoteept);
fs = new FileStream(@"e:\work\temp.html",
FileMode.OpenOrCreate, FileAccess.ReadWrite);
fs.Write(rcbytes, 0, rcbytes.Length);
Console.WriteLine("Accepted");
Process.Start(fs.Name);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
fs.Close();
rudp.Close();
}
}
}
Создаем клиента в отдельном проекте. Создаем серверное приложение в отдельном проекте. Сначала запускаем клиентское приложение, а затем – серверное приложение. В данной задаче передается файл html, который запускается на стороне клиента, как показано на скриншоте.
Базовым классом для создания UDP-соединения является класс UdpClient. Объект этого класса мы создаем с помощью команды
UdpClient udp= new UdpClient();
Можно также непосредственно в конструкторе указать номер порта, например,
UdpClient udp= new UdpClient(6312);
Однако более правильным вариантом является использование объекта класса IPEndPoint:
remoteIPAdr = IPAddress.Parse("127.0.0.1");
endPoint = new IPEndPoint(remoteIPAdr, remotePort);
UdpClient udp= new UdpClient(endpoint);
Этот последний вариант предполагает и одновременное соединение с указанным хостом. Другой способ реализуется так
remoteIPAdr = IPAddress.Parse("127.0.0.1");
endPoint = new IPEndPoint(remoteIPAdr, remotePort);
UdpClient udp= new UdpClient();
udp.Connect(endPoint);
Факт устанвления соединения в протоколе UDP не проверяется. Отсылка данных выполняется с помощью команды send.
byte [] bts=Encoding.ASCII.GetBytes(“Hello To EveryBodY”);
udp.Send(bts, bts.Length, endpoint);
Расмотрим теперь, как осуществить передачу файла на основе протокола UDP [8].
Серверная часть будет иметь следующий вид:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Threading;
namespace udp_server2
{
public class FileSender
{
public static IPAddress remoteIPAddress;
public static int remotePort = 5002;
public static UdpClient sender = new UdpClient();
public static IPEndPoint endPoint;
public static FileStream fs;
public static FileDetails fileDet = new FileDetails();
[Serializable]
public class FileDetails
{
public string FILETYPE = "";
public long FILESIZE = 0;
}
static void Main(string[] args)
{
try
{
remoteIPAddress = IPAddress.Parse("127.0.0.1");
endPoint = new IPEndPoint(remoteIPAddress, remotePort);
fs = new FileStream(@"e:\work\my.html", FileMode.Open,
FileAccess.Read);
if (fs.Length > 8192)
{
Console.WriteLine("Too long!");
sender.Close();
fs.Close();
Console.Read();
return;
}
SendFileInfo();
Thread.Sleep(4000);
SendFile();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
if (fs != null)
{
fs.Close();
sender.Close();
}
}
Console.WriteLine("File sent!!!");
Console.Read();
}
public static void SendFileInfo()
{
fileDet.FILESIZE=fs.Length;
fileDet.FILETYPE=fs.Name.Substring((int)fs.Name.Length-4,
4);
Console.WriteLine("Sent FileType {0}", fileDet.FILETYPE);
try
{
XmlSerializer fSer =
new XmlSerializer(typeof(FileDetails));
MemoryStream stream=new MemoryStream();
fSer.Serialize(stream,fileDet);
stream.Position=0;
byte[] bytes= new byte[stream.Length];
stream.Read(bytes,0,Convert.ToInt32(bytes.Length));
sender.Send(bytes,bytes.Length,endPoint);
stream.Close();
}
catch (Exception ex2)
{
Console.WriteLine("Bad Ser " + ex2.ToString());
Console.Read();
}
}
private static void SendFile()
{
byte[] bytes=new byte[fs.Length];
fs.Read(bytes,0,bytes.Length);
try{
sender.Send(bytes,bytes.Length,endPoint);
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
}
finally{
fs.Close();
sender.Close();
}
}
}
}
Здесь, в принципе, новым является сериализация внутреннего класса FileDetails. Внимательно рассмотрите это место в программе в части использования спецификаторов public (private недопустимо) и [Serializable]
Клиентская часть будет такой:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Threading;
namespace udp_client2
{
public class FileRecv
{
public int localPort = 5002;
public static UdpClient rudp;
public static IPAddress rapi = IPAddress.Parse("127.0.0.1");
public static IPEndPoint ipe;
public static FileStream fs;
public static byte[] bytes = new byte[0];
public static FileDetails fileDet = new FileDetails();
[Serializable]
public class FileDetails
{
public string FILETYPE = "";
public long FILESIZE = 0;
}
static void Main(string[] args)
{
ipe = new IPEndPoint(rapi, 5002);
rudp = new UdpClient(ipe);
Console.WriteLine("Получаем данные о файле ...");
GetFileDEtails();
Console.WriteLine(" данные о подучены ...");
Console.WriteLine("Получаем сам файл ...");
ReceiveFile();
Console.WriteLine(" файл получен ...");
}
private static void GetFileDEtails()
{
try
{
bytes = rudp.Receive(ref ipe);
Console.WriteLine("Connection established!!!!");
XmlSerializer xsr=new XmlSerializer(
typeof(FileDetails));
MemoryStream ms = new MemoryStream();
ms.Write(bytes, 0, bytes.Length);
ms.Position = 0;
fileDet = (FileDetails)xsr.Deserialize(ms);
Console.WriteLine("Received File Type {0}",
fileDet.FILESIZE);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.Read();
}
}
public static void ReceiveFile()
{
try
{
bytes = rudp.Receive(ref ipe);
fs = new FileStream(("temp." + fileDet.FILETYPE),
FileMode.OpenOrCreate, FileAccess.ReadWrite,
FileShare.ReadWrite);
fs.Write(bytes, 0, bytes.Length);
Console.WriteLine("File Saved!");
Process.Start(fs.Name);
Console.Read();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
fs.Close();
rudp.Close();
}
}
}
}
Опять же обратим внимание на то, что клиента следует запускать перед сервером.
ЛЕКЦИЯ 4. РАБОТА НА ОСНОВЕ ПРОТОКОЛА НТТР
предыдущий_раздел следующий_раздел следующая_лекция
предыдущая лекция
HTTP (hyper text transport protocol) – это протокол сетевого уровня (упрощенный), который размещается поверх TCP. Этот протокол используем для обмена WEB-ресурсами (документами, файлами, картинками). Сообщение в формате HTTP состоит из заголовков, несущих служебную информацию, и данных. Примерами заголовков являются
ACCEPT – определяет, какие виды документов может принимать клиент (текст, бинарные файлы, xml, картинки);
REFERER - , определяет интернет-адрес источника сообщения;
USER-AGENT – определяет информацию о браузере и т.д.
HTTP-соединение задеймтвует серверную сторону и клиентскую сторону.
Имеется возможность связи клиента и сервера через протокол HTTP(этот протокол использует Internet Explorer). Рассмотрим простой способ осуществить такую связь [1]. В рассматриваемо варианте соединения нет необходимости указывать номер порта. Сервер реализуется как удаленный объект (remote object), поэтому требуется посредник между сервером и клиентом — интерфейс. В интерфейсе нужно объявить методы сервера, которые следует сделать доступными из клиента. Вот пример сравнительно простого интерфейса:
using System;
public interface ISimpleObject
{
String ToUpper(String inString);
}
Единственным методом сервера является ToUpper. Этот метод принимает в качестве входного аргумента строку inString. Реализацию данного метода следует перенести в сервер. Само приложение сервера таково.
Приложение сервера на основе протокола HTTP
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
namespace Server
{
public class SimpleObject: MarshalByRefObject, ISimpleObject
{
public String ToUpper(String inString)
{
return(inString.ToUpper());
}
class Example8_8
{
static void Main(string[] args)
{
//
// TODO: Add code to start application here
HttpChannel channel = new HttpChannel(54321);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(SimpleObject),
"SOEndPoint", WellKnownObjectMode.Singleton);
Console.WriteLine("Press To Stop Server");
Console.ReadLine();
}
}
}
Обратим внимание на то, что в объявление класса сервера подключены созданный нами интерфейс и еще один интерфейс: MarshalByRefObject. Дальше следует выполнить реализацию метода ToUpper(). Метод Main() сервера осуществляет соединение с клиентом:
HttpChannel channel = new HttpChannel(54321); // Создаем канал связи
// снова через порт!
ChannelServices.RegisterChannel(channel); // Регистрируем канал
// в операционной системе
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(SimpleObject),
"SOEndPoint", WellKnownObjectMode.Singleton);
//определяем тип соединения "Simple Object End Point" и режим
// его работы Singleton (обслуживание одного клиента одним удаленным
// объектом)
Теперь рассмотрим сторону клиента:
Приложение клиента на основе протокола HTTP
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
class client
{
public static void Main()
{
HttpChannel h1=new HttpChannel(0);
ChannelServices.RegisterChannel(h1);
Object remoteOb=
RemotingServices.Connect(typeof(ISimpleObject),
"http://localhost:54321/SOEndPoint");
ISimpleObject so=remoteOb as ISimpleObject;
Console.WriteLine(so.ToUpper("so must be I say"));
}
}
Клиент должен получить доступ к удаленному объекту сервера. Это делается с помощью команды:
RemotingServices.Connect(typeof(ISimpleObject),
"http://localhost:54321/SOEndPoint");
Здесь использовано сетевое имяlocalhost; через двоеточие указан номер порта. Сетевое имя уникально идентифицирует компьютер. Следующая команда:
ISimpleObject so=remoteOb as ISimpleObject;
создает у клиента экземпляр объекта сервера. Отметим при этом, что используется имя интерфейса, а имя класса сервера вовсе не задействуется. Обращение к методу ToUpper сервера выполняется таким образом:
Console.WriteLine(so.ToUpper("so must be I say"));
Теперь рассмотрим считывание файла на основе протокола HTTP. Следующий пример демонстрирует простое скачивание файла с отображением на консоль:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
namespace htmlreading
{
class myhtml
{
static void Main(string[] args)
{
string query = @"e:\samko\excel_guide2.txt";
FileWebRequest req = (FileWebRequest)FileWebRequest.Create(query);
FileWebResponse resp = (FileWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream(),
Encoding.ASCII);
Console.WriteLine(sr.ReadToEnd());
resp.Close();
sr.Close();
Console.ReadLine();
}
}
}
Строка query представляет URI скачиваемого файла. Усложним этот пример следующим образом. Будем считывать html-файл и открывать его броузером. Наша программа имеет следующий вид.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Diagnostics;
namespace html_reading2
{
class myhtml2
{
static void Main(string[] args)
{
string query = @"e:\samko\excel_guide2.txt";
FileWebRequest req = (FileWebRequest)FileWebRequest.Create(query);
FileWebResponse resp = (FileWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream(),
Encoding.ASCII);
FileStream fs = new FileStream(@"e:\samko\new.html",
FileMode.OpenOrCreate, FileAccess.Write);
byte[] bc = Encoding.ASCII.GetBytes(sr.ReadToEnd());
Process.Start(fs.Name);
resp.Close();
sr.Close();
}
}
}
Здесь команда осуществляет запуск считанного файла. Файл считывется в массив байтов. Результат работы иллюстроирует следующий скриншот
Рис.4.1.
Покажем теперь, как адаптировать приведенный вариант программы к считыванию файла в Интернете.
Наш новый вариант имеет следующий вид:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Diagnostics;
using System.Security.Policy;
namespace html_reading2
{
class myhtml2
{
static void Main(string[] args)
{
string webstr = @"file://localhost/";
Uri baseUri = new Uri(webstr);
Uri query=new Uri(baseUri,@"e:\samko\new.html");
WebRequest req = WebRequest.Create(query);
WebResponse resp = (WebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream(),
Encoding.ASCII);
FileStream fs = new FileStream(@"e:\samko\new_new.html",
FileMode.OpenOrCreate, FileAccess.Write);
byte[] br = Encoding.ASCII.GetBytes(sr.ReadToEnd());
fs.Write(br, 0, br.Length);
Process.Start(fs.Name);
resp.Close();
sr.Close();
}
}
}
Строки
string webstr = @"file://localhost/";
Uri baseUri = new Uri(webstr);
Uri query=new Uri(baseUri,@"e:\samko\new.html");
задают адрес файла в Интернете. При считывании создается новый файл
FileStream fs = new FileStream(@"e:\samko\new_new.html",
FileMode.OpenOrCreate, FileAccess.Write);
Который открывается так же, как показано на рис.4.1.
ЛЕКЦИЯ 5. РАБОТА С XML-ДОКУМЕНТАМИ
предыдущий_раздел следующий_раздел следующая_лекция
предыдущая лекция
Список лекций
Продемонстрируем сначала создание документа вручную. Для этой цели будем использовать класс XmlDocument, XmlElement. Можно воспользоваться следующим кодом [11].
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.IO;
namespace xml1c
{
class myxml1c
{
public static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
XmlElement bookEl = doc.CreateElement("Book");
book