Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> скоростная передача данных 
:(
    Опции темы
IEHBR
Дата 29.11.2004, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 22.9.2004

Репутация: нет
Всего: нет



Мож кто нить знает способ передавать порядка тысячи сообщений в секунду.
Все чего смог добиться с помощью сокетов - 400 сообщений. Надо больше. smile
PM   Вверх
azesmcar
Дата 30.11.2004, 09:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



Какие сокеты используешь?? попробуй АПИ функции сокетов...
socket()
bind()
accept() итд итп...
кроме того используй потоки, а вообще какого размера сообщения???
Можешь попробовать запихнуть их сразу в одно сообщение с разделителем и отправить...
а там уже при получении разбить на части...

PM   Вверх
IEHBR
Дата 30.11.2004, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 22.9.2004

Репутация: нет
Всего: нет



использую апи, потоки (один на прием второй на посылку), очередь в оперативке.
сообщения длинной 100000 байт тк по моим подсчетам от длинны сообщения время на отправку/прием зависит не сильно - но все равно при любой обработке сообщения процесс тормозится на сотни - скорость падает до 100 сообщений в секунду.
Никаких других способов нет? smile
PM   Вверх
azesmcar
Дата 30.11.2004, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 3
Всего: 211



А если так...
берешь deque
пихаешь туда все свои сообщения
Начинаем отправку, два потока читают из очереди
один pop_front, другой pop_back а третий после отправки этой заполняет очередь
оба потока читают данные из deque и отправляют каждый до тех пор пока size()!=0
тут в принципе не помешало бы и провести общую оптимизацию кода, при стольких действиях каждая мелочь может повлиять на производительность...
Это вариант, но не могу точно сказать, зависит от того какая у тебя конкретная задача?
Отправить одно сообщение размером в 1000 * 100000 байт будет быстрее чем 1000 раз по 100000 байт...можно все же попробуешь отправить 1000 сообщений в одном...
Несколько сообщений имеет смысл отправлять если на разных событиях..а если тебе в любом случае нужно отправить эти 1000 сообщений и все они тебе известны то какой смысл все равно при такой скорости они весьма быстро окажутся в одном буффере, ты даже может не успеешь прочитать одно а в буффере будет второе...
PM   Вверх
Mad
Дата 30.11.2004, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 3
Всего: 19



Цитата(IEHBR @ 30.11.2004, 09:47)
сообщения длинной 100000 байт

Цитата(IEHBR @ 30.11.2004, 09:47)
скорость падает до 100 сообщений в секунду.

Ты и так получил 10к/с, что для отдельных посылок неплохо. Вопрос успевает ли твоя прога столько обрабатывать на приеме ?
код приведи.


--------------------
user posted image
PM MAIL   Вверх
IEHBR
Дата 1.12.2004, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 22.9.2004

Репутация: нет
Всего: нет



Делаю чтото вроде системы безопасности. Сообщений нужно минимум 24*25=600
в секунду. Сейчас тестим на максимуме - и поэтому длинна каждого 50000 байт.
/*код упращенный smile */
Код

bool InitClient()
{
///////////////////////////////// WSAStartup ///////////////////////////////////////////
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );
 err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 )
{  
 child->AddToErrorLog("could not find a usable WinSock DLL");  
 return false;
}

// Confirm that the WinSock DLL supports 2.2
if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
{
 child->AddToErrorLog("could not find a usable WinSock DLL");                                
 WSACleanup();  
 return false;
}

/////////////////////////////////// connect to server //////////////////////////////////////////  
struct sockaddr_in peer;
SOCKET skt=0;
int res;

memset(&peer, 0, sizeof(peer));
peer.sin_family = AF_INET;    
peer.sin_port = htons(4000);
peer.sin_addr.s_addr = inet_addr(m_ActiveServer_ip);

if( (skt = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
 child->ShowErrorMessage(WSAGetLastError());
 return false;
}

TRACE("\nconnecting to server. port=4000 ip=%s\n", m_ActiveServer_ip);

if( (res = connect(skt, (struct sockaddr*)&peer, sizeof(peer)) ) != 0 )
{
 child->ShowErrorMessage(WSAGetLastError());
 closesocket(skt);    
 return false;
}


///////////////////////////// get server connection //////////////////////////////////
SOCKET listen_skt, read_skt;
struct sockaddr_in local;
local.sin_family = PF_INET;  
local.sin_port = htons(4001);
local.sin_addr.s_addr = 0;

// create socket
if( (listen_skt = socket( PF_INET, SOCK_STREAM, 0) ) < 0)
{
           child->ShowErrorMessage(WSAGetLastError());
}

// bind address and port to listening socket
if( (res = bind(listen_skt, (struct sockaddr*)&local, sizeof(local)) ) < 0)
{
 child->ShowErrorMessage(WSAGetLastError());
}

// mark socket as listening
if( (res = listen(listen_skt, 5)) != 0)
{
 child->ShowErrorMessage(WSAGetLastError());
}
 
if( (read_skt = accept(listen_skt, NULL, NULL)) < 0)
{  
 child->ShowErrorMessage(WSAGetLastError());
}

m_sendsocket = skt;
m_readsocket = read_skt;

     AfxBeginThread(SendFunc, NULL);
AfxBeginThread(GetFunc, NULL);

     return true;
}

//bool InitServer() - аналогично InitClient()


UINT SendFunc(LPVOID pParam)
{
int skt = m_sendsocket;
long counter=0;
long size = 0;    
tag_message1 message;

for(long i=0; i<50000; i++)
 message.param[i] = 'W';
message.param[i] = '\0';

while(1)
{
 size = sizeof(tag_message1);
   
 // send size
 if( send(skt, (char*)&size, sizeof(long), 0) < 0)
 {
  DWORD s = WSAGetLastError();
  break;
 }
 
 char* p = reinterpret_cast<char*>(&message);  
 
 // send structure
 if( send(skt, p, size, 0) < 0)
 {
  DWORD s = WSAGetLastError();
  break;  
 }
}

return 0;
}




UINT GetFunc(LPVOID pParam)
{
int skt = m_readsocket;
long counter=0;
long ret;
long size = 0;  
tag_message1 message;

for(long i=0; i<50000; i++)
 message.param[i] = 'W';

message.param[i] = '\0';

while(1)
{
 // get parameter length
 size = sizeof(tag_message1);//strlen(message.param);  

 if( recv(skt, (char*)&size, sizeof(long), 0) <=0)
 {
  DWORD s = WSAGetLastError();
  break;
 }
 
 char* buff = new char [size];
 //tag_message1 pmsg = new tag_message1;
 
 long nBytes = recv( skt, buff, size, 0);
 tag_message1 *pmsg = reinterpret_cast<tag_message1*>(buff);
 
 TRACE("\ngot\t%d", counter++);
 delete [] buff;  
}

return 0;
}

мож кто подскажет как улучшить.... smile
заранее благодарен
PM   Вверх
Mad
Дата 1.12.2004, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Эксперт
Сообщений: 656
Регистрация: 18.10.2004
Где: Одесса

Репутация: 3
Всего: 19



Цитата(IEHBR @ 1.12.2004, 11:00)
if( recv(skt, (char*)&size, sizeof(long), 0) <=0)
{
  DWORD s = WSAGetLastError();
  break;
}

char* buff = new char [size];
//tag_message1 pmsg = new tag_message1;
 
long nBytes = recv( skt, buff, size, 0);
tag_message1 *pmsg = reinterpret_cast<tag_message1*>(buff);
 

Во первых recv не гарантирует, что примен 50к одним махом smile



--------------------
user posted image
PM MAIL   Вверх
n
Дата 1.12.2004, 15:29 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











там вместо recv на самом деле ф-ция readn след. вида:

Код

long readn(SOCKET skt, char* buffer, long length)
{
long cnt, rc;

cnt = length;

while(cnt > 0)
{
 rc = recv(skt, buffer, cnt, 0);

 if(rc < 0)
  return -1;


 if(rc == 0)
  return length - cnt;
 
 buffer += rc;
 cnt -= rc;
}

return length;
}

  Вверх
Fire-Plug
Дата 24.3.2005, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 102
Регистрация: 15.3.2005

Репутация: нет
Всего: 0



Цитата

Код

while(1)
{
 // get parameter length
 size = sizeof(tag_message1);//strlen(message.param);  
 . . . 
 char* buff = new char [size]; 
 //tag_message1 pmsg = new tag_message1;
. . . 
 delete [] buff;  
}

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

Размер сообщения заранее известен, поэтому естественней было бы выделить буфер для приема данных ВНЕ рабочего цикла:
Код

// get parameter length
size = sizeof(tag_message1);//strlen(message.param);  
char* buff = new char [size]; 

// Для автоматического удаления buff: 
std::auto_ptr<char> autoPtr(buff);

while(true)
{
. . .
}

У вас что, и в реальном коде память под сообщение выделяется каждый раз?
Это может быть оправданно только тогда, когда приём и обработка сообщения происходит асинхронно, для чего сообщение требуется поместить в некую выходную очередь.

Затем, на скорость передачи в реальных условиях влияет и топология вашей сети, и ее технические параметры, а также характеристики "железа" и OC на узловых PC, где вы запускаете вашу систему. Т.е. проблема может быть в области средств связи, а не программирования.

У меня сейчас где-то подобная задача, только разница в том, что размер "сообщения" - переменный. Но обработка сообщения происходит в цикле приёма, поэтому память под приёмный буфер распределена заранее и только, если придет сообщение бОльшего размера, чем размер буфера, то последний перераспределяется. Загловок сообщения содержит его размер, поэтому длина передачи всегда известна.
Так вот в секунду передаётся
~10K * 15[1/сек] * 60 каналов (в среднем, т.к. зависит от числа клиентов) = ~9000 К/сек.
Серверное приложение сидит на P4 2 GHz, NIC - 100 Mbps интегрированная на маме, ОС - Win2000 Server SP4. Сеть - 100 Mbps с массой раутеров и сегментов. При этом загрузка сетевых ресурсов PC-сервера по результатам измерений находится в области 50%.
Добавлено @ 08:22
Во, блин, не обратил внимания - тема-то уже не новая... smile
--------------------
Объясни другому - поймешь сам (Народная примета)
PM MAIL   Вверх
knave
Дата 13.4.2005, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 6.3.2003
Где: Санкт-Питербург ( Россия)

Репутация: 1
Всего: 5



Надо паковать твои данные. Не пакуя ты неполучиш бльшой скорости при передаче больших объемов. Игры обычно пакуют свои блоки данных, которыми они обмениваются по сети, иначе никак.

Да, не следует слать большие блоки заодин раз. Если в сокет запихать скжем 4кб то они на клиенте косо примутся или затрутся тем что пришло после.

Вообщем бери свой блок котрый ты хочеш послать, пакуй, шли, на том конце распаковывай. Шли при этом небольшими порциями, скажем по 512 байт. Скорость при пковке существенно возрастет, так как уменьшится врмя передачи куска. Распаковка произойдт значительно быстрее чем передача непакованного блока. Для передачи сипользуй UDP - по приходу пакета распаковывай его, как закончиш сним работу шли ответ. Очередной кусок шли только по получении ответа от клиента. Можно не обрабатывать, а кэшировать и потом обрабатывать из кэша. НО очередной кусок данных шли толко после того как ты его считаеш и поместиш в очередь. Для этог север должен ждать от клиента ответ - блок принят. Если это не сделать то твои блоки затрутся в сокете (даже при TCP, так как он гарантирет доставку пакетов, а как они там дальше это уже доло сокетов.).


--------------------
С наилучшими пожеланиями !!!
PM MAIL ICQ   Вверх
Arush
Дата 25.5.2005, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.11.2003

Репутация: нет
Всего: 1



На самом деле надо использовать OVERLAPPED режим передачи, как об этом написано у мелкософт.
Попробуй поискать в МСДН по OVERLAPPED или efficient network programming. Там должны быть примеры.
Суть в том, что когда используется обычный send то возврат из функции происходит только после отправки данных, когда ты используеь асинхронный оежим - возврат происходит сразу, а после отправки данных система уведомляет твой код, что они отправлены.

PM MAIL   Вверх
knave
Дата 26.5.2005, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 320
Регистрация: 6.3.2003
Где: Санкт-Питербург ( Россия)

Репутация: 1
Всего: 5



Так это реально то не увеличит количество отправляемых сообщений в еденицу времени. Ну наставиш ты очередь из миллиона мессаг и что, скорость передачи по сети всеравно будет прежней.


--------------------
С наилучшими пожеланиями !!!
PM MAIL ICQ   Вверх
Arush
Дата 27.5.2005, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.11.2003

Репутация: нет
Всего: 1



А ты проверял?
Мелкософт не спроста это все затеяла и неспроста пишет что производительные сетевые приложения надо писать именно так.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0833 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.