Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3  Все   Вниз
  Печать  
Автор Тема: сбор данны по сети  (Прочитано 99790 раз)
0 Пользователей и 1 Гость смотрят эту тему.
locator
Постоялец

ru
Offline Offline

« : 09-06-2013 13:33 » 

Доброго времени суток! есть девайс, собирающий данные (на шине PC/104), сам компьютер PC/104 соединен
через wi-fi с ноутбуком. Девайс формирует данные в виде пакетов размером около 600 байт. Интервал обновления
пакетов около 1мс (частота 1кГц). Задача в том, чтобы посылать пакеты в ноут с максимальной скоростью
(которую позволяет соединение wi-fi 50мбит/c). Я создал сервер, и тупо написал поток передачи пакетов клиенту,
вот потоковая функция:
Код: (C++)
DWORD WINAPI SendData(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock = ((SOCKET *)client_socket)[0];
        union
        {
                DEV_DATA dat; // структура данных от девайса рамером 600 байт
                char buff[sizeof(DEV_DATA)];
        };
        while(1)
        {  
           send(my_sock, buff, sizeof(DEV_DATA), 0);
           Sleep(10); // задаю 100 раз в секунду передачу пакетов
        }
    return 0;
  }
Но клиент на ноутбуке принимает битые пакеты или вообще зависает (писал с
компонентом TClientSocket на билдере). Задал интервал передачи в потоке 5 раз
 в секунду (написал Sleep(200)), все нормально передается. Я так понимаю, что
пакеты можно намного чаще передавать, чем 5  раз в секунда. Как мне грамотно
написать процесс передачи/приема пакетов (так, чтобы скорость обмена была максимальной) ? 
В инете про это никто  не пишет (все статьи о том, как соединить сервер с клиентом,
 не более того  Здесь была моя ладья...).  Может ссылки полезные дадите?   
На PC/104 установлена winxp, на ноуте win7.
Спасибо за ответы!
« Последнее редактирование: 09-06-2013 14:02 от locator » Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 09-06-2013 14:32 » 

Ну... тут скорей нужна математика.

50Мбит/с ~ 5Мб/с

делим на 600, получаем 8000 пакетов в сек

зы... я не ошибся в расчетах?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
locator
Постоялец

ru
Offline Offline

« Ответ #2 : 09-06-2013 16:07 » 

немного ошибся, в пакет добавляется заголовок ip, поэтому скорость
поменьше будет. и как это реализовать?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 09-06-2013 16:11 » 

А собрать несколько пакетов в обший пакет?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
locator
Постоялец

ru
Offline Offline

« Ответ #4 : 09-06-2013 17:16 » 

а это как?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 09-06-2013 18:32 » 

locator, с позиции API сокетов пофиг, посылаешь ли ты по гигабитному ethernet, через WiFi или по модему на 1200 бод: интерфейс один и тот же. Битых пакетов программа получить не может. Пакет либо будет получен целиком, либо не будет получен совсем. Напрашивается вывод, что у тебя ошибка в программе (в какой — тебе виднее, код мы не видим).

Подмечу, что упрощенная формула, применяемая к ethernet (байт/с = бит/с ÷ 10), в WiFi не работает. Фактическая скорость передачи будет зависеть от множества факторов, предсказать которые заранее невозможно. Это сеть с негарантированной пропускной способностью. Кстати, служебные данные WiFi передаются на скоростях 1 или 2 Мбит/с, а с большими скоростями передается полезная нагрузка (в данном случае IP-пакеты). Т.к. WiFi — сеть с разделяемой средой передачи, то возможны коллизии и есть переменная задержка начала передачи (и повторной передачи пакета).  Еще есть подтверждение приема пакета. При работе через точку доступа пакет проходит по эфиру дважды. В общем, протокол сложен и для оценки приблизительной максимальной скорости стоит делить не на 10, а на 25. А есть и еще понижающие скорость факторы: загрузка эфира (разделение частотного канала разными пользователями WiFi), помехи (возможны повторные пересылки и понижение скорости передачи).
Для точного расчета задержек передачи нужно углубляться в чтение стандартов. Попробую очень грубо прикинуть...
Скажем, на скорости 54 Мбит/с блок данных в 600 байт (плюс 28 байт на заголовки IP и UDP) передастся за ≈93 мкс. Накинем на служебные нужды: пусть получится порядка 150 мкс. Двойной проход по эфиру: уже 300 мкс. Два подтверждения получения пакета, задержки, помехи, коллизии: 1000 пакетов в секунду — это оптимистичный прогноз, хотя и достижимый при должных условиях. Куда производительнее будет собирать данные в буфер и пересылать более крупными партиями.
« Последнее редактирование: 09-06-2013 18:42 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
locator
Постоялец

ru
Offline Offline

« Ответ #6 : 09-06-2013 19:09 » 

ну какая может быть ошибка, все копировалось с известных программ:
Код: (C++)
int nclients = 0;

 while((client_socket = accept(mysocket, (sockaddr *)&client_addr, &client_addr_size)))
        // цикл извлечения запросов на подключение из очереди клиентов
    {
       nclients++;

      HOSTENT *hst;

      hst = gethostbyaddr((char *)&client_addr.sin_addr.s_addr, 4, AF_INET);
   
     DWORD thID;
      CreateThread(NULL, NULL, SendData,  &client_socket, NULL, &thID);

      if(nclients == 1) break; // нам больше одного клиента не надо
    }


// функция сервера (передает пакеты)
DWORD WINAPI SendData(LPVOID client_socket)
  {
    SOCKET my_sock;
    my_sock = ((SOCKET *)client_socket)[0];
        union
        {
                DATA data;
                char buff[sizeof(DATA)];
        };

        while(1)
        {  
           send(my_sock, buff, sizeof(DATA), 0);
           Sleep(10);
        }
 
    return 0;
  }

// функция клиента
void __fastcall TForm1::ClientSocket1Read(TObject *Sender,
      TCustomWinSocket *Socket)
{
 
  if(ClientSocket1->Active == false) return;

  int len = Socket->ReceiveLength(); // получили длину пакета
//если более 5 раз/с передача, то длина получается любой, 1000 байт, 2000 байт... (почему ?????)

  char *Buff = new char[sizeof(DATA)];

  AnsiString s; s.SetLength(len);

  Socket->ReceiveBuf(Buff, len);

  strcpy(data, Buff); // массив data объявлен глобальным
}

Кстати, если весь обмен тестировать на локальном компе, то все летает..... действительно около 1000 раз/с.
Я просто не понимаю, как передаются данные, например, фильмы, музыка по сетевым протоколам....? Видимо, как-то
по другому,  а как?


Добавлено через 2 минуты и 32 секунды:
Finch, двинь идейку пожалуйста  Улыбаюсь
« Последнее редактирование: 09-06-2013 19:11 от locator » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 09-06-2013 19:30 » 

locator, у тебя сокеты UDP или TCP?

А программа — ужас.
« Последнее редактирование: 09-06-2013 19:33 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
locator
Постоялец

ru
Offline Offline

« Ответ #8 : 10-06-2013 03:58 » 

сокеты TCP конечно
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 10-06-2013 04:21 » 

locator, когда мне встречалась такая задача, самый действенный вариант каждый раз оказывался такой:
запускается несложного содержания поток считывания, работающий максимально быстро (понадобится ознакомиться с описанием функций timeGetDevCaps , timeBeginPeriod , CreateEvent ,WaitForSingleObject )

поток имеет некоторый не сильно большой приёмный буфер (килобайты) . Одна итерация запрашивает (методом receive) из сокета данные размером с этот буфер, и всё, что считалось, через синхронизатор (критическая секция) дописывает во внешний приёмный буфер (бОльших размеров). Затем производится ожидание в 1 мс - сбрасывается созданный для этих целей хендл события и вызывается WaitForSingleObject  для него, затем идёт новая итерация

Таким образом во внешнем буфере имеем актуальный поток данных, разгружая при этом сокет и не допуская потерь на этом уровне). При работе с внешним буфером, через тот же синхронизатор вытаскиваем порцию данных (копируем и разлочиваем, собственно, чтобы не затормаживать поток) и дальше "спокойно" анализируем.

Не претендую на идеальность способа, но он работает )

Всё то же самое будет работать и с UDP

Добавлено через 2 минуты и 35 секунд:
данные, передаваемые по wi-fi лучше, конечно же, собирать в пакеты. Попробуй ещё и сжимать , если скорость не устроит
« Последнее редактирование: 10-06-2013 04:24 от Алексей++ » Записан

locator
Постоялец

ru
Offline Offline

« Ответ #10 : 10-06-2013 05:24 » 

значит, тотальная буферизация нужна.
Известно, что у компонента TClientSocket есть поток встроенный.
Алексей++, это случайно не тот поток, о котором ты говоришь?
И еще я не понимаю: на передатчике пакетов должен стоять сервер
или клиент? Или это без разницы?
Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #11 : 10-06-2013 05:26 » 

locator, а что Вы понимаете под "битыми" пакетами? Как правильно сказал RLX в tcp/ip и udp/ip пакет битым прийти не может, его должны отфильтровать на протокольном уровне - там контрольные суммы передаются. Могут быть потери, если используете udp, и это значит, что, скорее всего, Вы не успеваете забирать сообщения из сокета. В качестве варианта - можно попробовать увеличить буфера приёма через setsockopt(fd, .., SO_RCVBUF,..), но более правильным будет вариант, который тут предложили - попробовать объединить пакеты, т.е. за раз выдавать информацию не одного пакета, а двух, но зато с вдвое меньшей частотой.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 10-06-2013 05:39 » 

locator, мне неизвестно, что есть в TClientSocket , я билдером не пользовался. В самой WinAPI при создании сокета вроде никаких потоков не создаётся.

Сервер должен стоять на сервере (на приёмнике) - он нужен для принятия подключения от клиента в случае TCP. Но уже в передаче и приёме данных сервер никак не участвует
Записан

sss
Специалист

ru
Offline Offline

« Ответ #13 : 10-06-2013 05:41 » 

locator, а что Вы понимаете под "битыми" пакетами? Как правильно сказал RLX в tcp/ip и udp/ip пакет битым прийти не может,

Может. Две последовательные передачи могут быть приняты одновременно или даже разрезаться по неравным частям.
Например:

Передаём три раза по 600 байт.
Варианты приёма:
1) Три раза по 600 байт.
2) Один раз 1800 байт
3) 1500 + 300
..

Надеюсь проблема понятна.

P.S.: Для TCP сокета можно ещё выключить алгоритм Нагла (Nagle).

« Последнее редактирование: 10-06-2013 05:43 от sss » Записан

while (8==8)
locator
Постоялец

ru
Offline Offline

« Ответ #14 : 10-06-2013 06:02 » 

locator, а что Вы понимаете под "битыми" пакетами?  
я смтотрю длину пакета функцией Socket->ReceiveLength(), и длина все время разная
получается (1000, 2000 байт). Получается, что пакет не принят. Или сразу два пакета
прилетело.
« Последнее редактирование: 10-06-2013 06:03 от locator » Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #15 : 10-06-2013 06:10 » 

locator, а что Вы понимаете под "битыми" пакетами? Как правильно сказал RLX в tcp/ip и udp/ip пакет битым прийти не может,

Может. Две последовательные передачи могут быть приняты одновременно или даже разрезаться по неравным частям.
Например:

Передаём три раза по 600 байт.
Варианты приёма:
1) Три раза по 600 байт.
2) Один раз 1800 байт
3) 1500 + 300
..

Надеюсь проблема понятна.

P.S.: Для TCP сокета можно ещё выключить алгоритм Нагла (Nagle).
В TCP нет понятия пакетов, там - поток, соответственно данные могут хоть по байту приходить - если их правильно принимать (например использовать в recv() флаг MSG_WAITALL в unix-подобных ОС, или просто дочитывать до требуемой длины в win), то таких проблем быть не должно. При этом битых пакетов всё-равно быть не может - сообщение либо приходит, либо нет, в tcp/ip если не было подтверждения о получении, то сообщение будет выслано повторно, в udp хуже - просто выбросят и всё.  А про алгоритм Нагла Вы правильно сказали - в данной ситуации может немного помочь.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 10-06-2013 06:11 » 

Я повторю вопрос.

По скорости все согласовано?
Успеваешь передавать пакеты?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
darkelf
Молодой специалист

no
Offline Offline

« Ответ #17 : 10-06-2013 06:12 » 

locator, в tcp нет пакетов. Вам надо не просто принимать сообщения, а ещё их правильно собирать.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 10-06-2013 06:15 » 

сокеты TCP конечно

Тогда для буферизации ничего делать не надо. Алгоритм отложенной отправки сам решит, когда отправлять очередной пакет. А для API TCP сокет представлен как поток байт, а не набор пакетов. Соотв., тебе нужно структуировать данные, чтобы можно было понять начало и конец блока данных. Например, так:

Код: (C++)
typedef struct _packet_buffer{
    uint16 size;
    DEV_DATA dat;
    void _packet_buffer(void) {
        size = sizeof(_packet_buffer);
    };
} packet_buffer_t;

// ...
packet_buffer_t buffer;

//...
send(socket, (void *)&buffer, sizeof(packet_buffer_t), 0);

При приеме считать sizeof(uint16) байт, после чего считать указанное число байт. Если объем считанных данных недостаточен, значит надо повторить считывание (обычных блокируемый ввод-вывод решает эту проблему).

Добавлено через 5 минут и 45 секунд:
locator, а что Вы понимаете под "битыми" пакетами? Как правильно сказал RLX в tcp/ip и udp/ip пакет битым прийти не может,

Может. Две последовательные передачи могут быть приняты одновременно или даже разрезаться по неравным частям.
Например:

Передаём три раза по 600 байт.
Варианты приёма:
1) Три раза по 600 байт.
2) Один раз 1800 байт
3) 1500 + 300
..

Надеюсь проблема понятна.

P.S.: Для TCP сокета можно ещё выключить алгоритм Нагла (Nagle).

Это не «битые пакеты», а невыровненные данные. Потому как потоки и пакеты — разные концепции.
« Последнее редактирование: 10-06-2013 06:28 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
locator
Постоялец

ru
Offline Offline

« Ответ #19 : 10-06-2013 06:23 » 

то бишь читать по одному байтику из принимаемого потока, и разделять
заголовки пакетов?
Или функцией Socket->ReceiveBuf(Buff,len) складывать буферы Buff в другой
большой буфер (или очередь), и уже оттуда анализировать цепочку байтов
(отделять заголовки пакетов)?
« Последнее редактирование: 10-06-2013 06:26 от locator » Записан
darkelf
Молодой специалист

no
Offline Offline

« Ответ #20 : 10-06-2013 06:26 » 

locator, зачем побайтно? Читать по столько, по сколько читается, просто написать алгоритм разбора, например конечный автомат.
Или функцией Socket->ReceiveBuf(Buff,len) складывать буферы Buff в другой
большой буфер (или очередь), и уже оттуда анализировать цепочку байтов
(отделять заголовки пакетов)?
можно и так.
« Последнее редактирование: 10-06-2013 06:27 от darkelf » Записан
sss
Специалист

ru
Offline Offline

« Ответ #21 : 10-06-2013 06:26 » 


Это не «битые пакеты», а невыровненные данные. Потому как потоки и пакеты — разные концепции.


Человек передаёт и ожидает пакеты через поток TCP. В TCP нет пакетов? Есть(!) - используются для организации потока.. И вообще - есть связь с установлением соединения и без установления соединения. 
« Последнее редактирование: 10-06-2013 06:29 от sss » Записан

while (8==8)
darkelf
Молодой специалист

no
Offline Offline

« Ответ #22 : 10-06-2013 06:28 » 

sss, на прикладном уровне, на котором работает человек - пакетов нет, как нет секторов при работе с диском.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 10-06-2013 06:29 » 

locator, перечитай пост, я его дополнил примером.
https://forum.shelek.ru/index.php/topic,29445.msg289155.html#msg289155

Добавлено через 3 минуты и 55 секунд:

Это не «битые пакеты», а невыровненные данные. Потому как потоки и пакеты — разные концепции.


Человек передаёт и ожидает пакеты через поток TCP. В TCP нет пакетов? Есть(!) - используются для организации потока.. И вообще - есть связь с установлением соединения и без установления соединения. 

Чушь говоришь, дорогой. Ты приравниваешь программный буфер отправки к транспортному пакету и программному буфер приема, да еще для протокола, не гарантирующего пакетную разбивку. Отправь 600 байт по сети с TCP MSS равным 400!
« Последнее редактирование: 10-06-2013 06:33 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
sss
Специалист

ru
Offline Offline

« Ответ #24 : 10-06-2013 06:33 » new

sss, на прикладном уровне, на котором работает человек - пакетов нет, как нет секторов при работе с диском.
Блин где Вы взяли что TCP поточный, а UDP пакетный? Ещё раз - есть связь с установлением соединения и без установления соединения.  
Все протоколы используют пакеты..
Записан

while (8==8)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 10-06-2013 06:36 » 

sss, личные убеждения — это святое, но не при обмене информацией. Поднимись над IP и углубись в API.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
locator
Постоялец

ru
Offline Offline

« Ответ #26 : 10-06-2013 06:37 » 

из сказанного выше, я понял что передаваемые мной данные система
делит на блоки и передает эти блоки, причем размером блоков я уже
не могу управлять.  За одну посылку пакета 600 байт передаться может как
600, так и 400 байт, тогда остаток принимается уже в следующий прием.
Записан
sss
Специалист

ru
Offline Offline

« Ответ #27 : 10-06-2013 06:38 » 

RXL, вот что я знаю - есть сети с коммутацией пакетов и коммутацией каналов. Хотите поговорить об этом? Или это мои личные убеждения?

Добавлено через 2 минуты и 44 секунды:
А вот нашёл - Протокол не сохраняющий границы сообщений, обычно называют протоколом, основанном на потоке.
« Последнее редактирование: 10-06-2013 06:41 от sss » Записан

while (8==8)
darkelf
Молодой специалист

no
Offline Offline

« Ответ #28 : 10-06-2013 06:44 » 

sss, имхо, Вы немного путаете, как оно реализовано "внизу" и какой интерфейс имеет "вверху". То, что там бегают пакеты никак не влияет на его интерфейс с верхом, а этот интерфейс таков, что предоставляется поток данных, без разбиения на пакеты - можете хоть побайтно вычитывать - если будете успевать - всё будет работать и данные теряться не будут. Ещё раз приведу аналогию с жестким диском - там внутри сектора, на уровне ФС - блоки и кластеры, но тем не менее, когда Вы работаете через интерфейс ОС типа read()/write() - Вас это как-то мало волнует - для Вас это просто поток байтов, хотя физически он там может быть очень неплохо быть разбросанным по диску..
« Последнее редактирование: 10-06-2013 06:46 от darkelf » Записан
sss
Специалист

ru
Offline Offline

« Ответ #29 : 10-06-2013 06:46 » 

из сказанного выше, я понял что передаваемые мной данные система

Вам придётся передавать пакеты через поток. Вначале - длина пакета, затем данные.  На приёмной стороне парсить.. Иначе это всё лишь предположения и танцы с бубнами.. Это очень вылезет на дальнем расстоянии в условиях больших задержек пакетов на маршрутизаторах.. Там будут абсолютно непредсказуемые буферы приходить.. Но зато всегда по порядку
Записан

while (8==8)
Страниц: [1] 2 3  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines