Количество отправленных данных

 
0
 
.NET
ava
Modul | 10.11.2007, 14:42
В продолжении тем:

http://forum.vingrad.ru/topic-167333.html
Здесь разговор шел об отправленных байтах, а свелся к принятым.
Для принятых все просто.

мой топик
http://forum.vingrad.ru/topic-149187.html
все еще не понятно...
Неизвестно, сколько данных ушло в сеть.

Как известно, метод Write() класса NetworkStream не поддерживает
события, чтобы получить текущее количество отправленных данных
в потоке. Хотя и можно сделать, но надо знать все равно отправленное число.


private NetworkStream ns;
ns.Write(data, 0, data.Length);


Данные пишуться в поток быстро, а вот отправляются в зависимости
от пропускной способности сети, буфера передачи TCP-модуля,
настроек Win и т.д.

Поизучав методы, можно предложить простой метод с использованием
сетевого интерфейса и таймера:


public partial class Form1 : Form
{
public NetworkInterface[] adapters;
public IPv4InterfaceStatistics stats;
public int b1 = 0;


public Form1()
{
InitializeComponent();

// Количество байт (b1) на момент определения в Windows
adapters = NetworkInterface.GetAllNetworkInterfaces();
stats = adapters[0].GetIPv4Statistics();
b1 = (int)stats.BytesSent;

}


// Таймер на форме с интервалом в 1 секунду
private void timer1_Tick(object sender, EventArgs e)
{

// Запоминаем b1
stats = adapters[0].GetIPv4Statistics();
int b2 = (int)stats.BytesSent;

// Отправлено в секунду
int delCurrent = b2 - b1;

// Скорость KB/c
float v = (float)delCurrent / (1 * 1024);

b1 = b2;

}


}
}



Недостаток:
- Если работают другие программы, есть небольшая ошибка,
так как NetworkInterface считает весь исходящий трафик
(небольшой обмен существует)

added later:
По материалам других форумов:

Цитата


Приемные буферы используются и в TCP, и в UDP для хранения полученных данных, пока они не будут считаны приложением. В случае TCP доступное пространство в приемном буфере полностью установленных соединений сокета представляет собой окно Receive Window, размер которого модуль TCP сообщает партнеру по соединению и которое может изменяться в течение TCP-сессии. В результате приемный буфер сокета TCP никогда не может переполниться, поскольку собеседнику не разрешается отправлять данные, размер которых превышает размер окна. Если партнер по соединению по каким-либо причинам игнорирует объявленное окно и отправляет данные, превышающие его размер, модуль TCP приемника просто отбросит эти данные и не пошлет соответствующего подтверждения.



Вот поэтому нет смысла писать в поток частями, все равно данные идут в приемный буфер.

Мысль:
А как можно задать этот буфер в Win и увязать это с методом Write() ???


Comments (12)
ava
arilou | 27.12.2007, 22:51 #
Modul, поздно я это увидел. Все просто - надо отнаследоваться от Stream, завернуть внутри NetworkStream и дописать функционал по подсчету отправленных и принятых байт.
ava
mr.DUDA | 28.12.2007, 11:10 #
Вариант - использовать не stream напрямую а BufferedStream или BinaryWriter. Ещё вариант - вызывать Flush после каждой отправки.
ava
Modul | 07.01.2008, 03:19 #
mr.DUDA
Цитата


вызывать Flush после каждой отправки



Ничего не дает.
Тут же используется не сам сокет, а потоки ввода-вывода (абстракция сокета).


arilou
Цитата


Все просто - надо отнаследоваться от Stream, завернуть внутри NetworkStream и дописать функционал по подсчету отправленных и принятых байт.


Ты как-то хотел помочь, но времени не хватило :biggrin

По принятым мне все ясно, как сделать с отправленными - прогрессбар.

Спасибо !
ava
tol05 | 07.01.2008, 11:59 #
да точно также. Отправляй их частями и изменяй прогресс-бар. Усложнять приложение мониторингом системмных устройств ИМХО не стоит.
Ну а то, что данные могут быть в это время буфере... ну и что? А если при передаче вообще пакет патеряется? Ты что-ли в этом виноват будешь?
ИМХО твоя задача - просто показать, что твое приложение отправило байты и показать сколько.
ava
Modul | 07.01.2008, 14:35 #
Цитата


Отправляй их частями и изменяй прогресс-бар.



Мне уже 3 раза советовали так и сделать.
Я уже пробовал так.
Данные бросаются в поток сразу (це ж компутер), а хохма в том, что отправляются потепенно.


А реально ничего не получается !!!



Цитата


просто показать



ИМХО плохо, пользователю надо видеть РЕАЛЬНЫЙ РЕЗУЛЬТАТ - прогресс !!!

Вот прекрасный пример(прикреплен в файле), но он для ПРИНЯТЫХ байтов,
а кто сможет сделать для ОТПРАВЛЕННЫХ.
ava
tol05 | 07.01.2008, 22:05 #
в коде формы NetworkFileSender-а измени код для

// Loop through the file stream of the local file
while ((bytesSize = fstFile.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
// Write the data that composes the file to the network stream
strRemote.Write(downBuffer, 0, bytesSize);
}

на код

int bytesCounter = 0;
// Loop through the file stream of the local file
while ((bytesSize = fstFile.Read(downBuffer, 0, downBuffer.Length)) > 0)
{
bytesCounter += bytesSize;
// Write the data that composes the file to the network stream
strRemote.Write(downBuffer, 0, bytesSize);
this.Invoke(new UpdateProgressCallback(this.UpdateProgress), new object[] { bytesCounter, FileSize });
}

UpdateProgress аналогична одноименной ф-ции Receiver-а
ava
arilou | 08.01.2008, 13:27 #
tol05, а разве что-то изменится таким образом? оно ведь в буфер пишет. по идее, надо еще вызывать strRemote.Flush().

А вообще, по науке, надо использовать I/O completion callback. В NetworkStream это реализовано с помощью Begin/End Read/Write. Но это посложнее немного.
ava
tol05 | 08.01.2008, 14:01 #
да я просто принцип пытался показать и не более. По крайней мере у меня при отправке файла прогресс-бар плавно бежит, а значит - процесс идет. По поводу strRemote.Flush() - не возражаю. Просто я показал, что данные из программы ушли (второй раз мы их передавать уже не будем, а то что они в буфере накапливаются - это уже другой вопрос)

Просто во-первых просили сделать также, как в Read, только в Write smile
В во-вторых, Begin/End Read/Write погоды не сделает, поскольку это тот же Write, только еще в одном, дополнительном потоке. После вызова BeginWrite запускается отдельный поток, где идет синхронный Write, по окончанию которого вызывается callback.

А у нас уже есть этот дополнительный поток. Мы APM вручную сделали и

this.Invoke(new UpdateProgressCallback(this.UpdateProgress), new object[] { bytesCounter, FileSize });

это и есть наш callback... И пока синхронный Write отрабатывается, можем работать в своем основном потоке.

ava
arilou | 08.01.2008, 14:08 #
Цитата (tol05 @ 8.1.2008, 14:01 findReferencedText)
В во-вторых, Begin/End Read/Write погоды не сделает, поскольку это тот же Write, только еще в одном, дополнительном потоке. После вызова BeginWrite запускается отдельный поток, где идет синхронный Write, по окончанию которого вызывается callback.

Неа, там I/O completion ports юзаются (по крайней мере это контролируется через какое-то свойство, но не помню, как оно называется). Они на системных потоках работают. При этом приложение автоматически скалируется, когда тебе надо параллельно много коннектов держать -- всем управляет ОС. На них W2K3 server может держать до 5000 одновременных коннектов, и не тупить.
ava
tol05 | 08.01.2008, 14:48 #
Цитата (arilou @ 8.1.2008, 13:08 findReferencedText)
Неа, там I/O completion ports юзаются

да, правильно. Я что-то затупил по performance...

Но все равно, к вопросу апдейта прогресс-бара это не относится. :)

P.S. Или ты имеешь в виду, что callback с BeginWrite система вызовет после того как передаст данные? Ну... может быть... Надо разбираться. smile
ava
arilou | 08.01.2008, 18:09 #
Цитата (tol05 @ 8.1.2008, 14:48 findReferencedText)
.S. Или ты имеешь в виду, что callback с BeginWrite система вызовет после того как передаст данные? Ну... может быть... Надо разбираться

Ага, именно так smile
ava
Modul | 09.01.2008, 15:36 #
Спасибо, мужики за ответы.

Не так то все просто, как кажется на самом деле !!!

Этот пример я и так разобрал, он у меня работал (вроде smile )
так как Вы предлагали...

Но вопрос видимо несколько шире - прога на почтовый сервер письмо отправляет.

Приду домой, приатачу другой пример...
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  mr.DUDA   arilou   Modul   tol05
advanced
Submit