Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2010.09.05;
Скачать: [xml.tar.bz2];

Вниз

TServerSocket/TClientSocket SendText   Найти похожие ветки 

 
Андрей   (2008-10-29 14:36) [0]

Уважаемые, не подскажете, от чего может зависеть скорость передачи/приема пакетов? При тесте на локальной машине все летает, а как только подключаю в локальную сеть, так начинаются задержки отправки/приема (приложение работает по принципу: клиент отослал на сервер пакет, тот его разослал всем подключившимся, в том числе и тому, кто отослал). На сеть грешить сложно, т.к. обычные чаты в ней работают практически без задержек. Есть различие в скорости на чем делать клиента/сервер синхронный/асинхронный режимы?


 
Сергей М. ©   (2008-10-29 14:49) [1]


> начинаются задержки отправки/приема


В чем и как это выражается ?


> Есть различие в скорости на чем делать клиента/сервер синхронный/асинхронный
> режимы?


Принципиальных различий нет.


 
Сергей М. ©   (2008-10-29 14:56) [2]


> тот его разослал всем подключившимся


Если сервер однопоточный, то при росте числа активных клиентов рост задержки будет неминуем.


 
tesseract ©   (2008-10-29 20:04) [3]


>  клиент отослал на сервер пакет, тот его разослал всем подключившимся,
>  в том числе и тому, кто отослал)


Так правильно, ты сеть по геометрической прогрессии загружаешь. Каждый подключённый клиент это увеличение трафика на КолКлиентов*2.  И Если ты работаешь не по UDP - начнуться проблемы.


> Принципиальных различий нет.


Огромные ! Асинхронный режим это чисто придумка MS  - там прослойка (не спорю написана хорошо) над чисто синхронными сокетами.


 
Сергей М. ©   (2008-10-29 20:21) [4]


> tesseract ©   (29.10.08 20:04) [3]


> Огромные

Да не трынди)


> Асинхронный режим это чисто придумка MS


Ты не любишь кошек ? Ну тогда и не советуй как их готовить !)


 
Сергей М. ©   (2008-10-30 08:11) [5]


> tesseract ©   (29.10.08 20:04) [3]


Извини за резкость


 
Андрей   (2008-10-31 20:28) [6]


>В чем и как это выражается?


Подключены 2 клиента. Задержка между отправкой пакета и приходом его же отправляющему клиенту несколько секунд.


 
Сергей М. ©   (2008-11-01 08:25) [7]


> Андрей   (31.10.08 20:28) [6]


Думаю что у тебя ошибка в программе.


 
Андрей   (2008-11-01 14:46) [8]

Если не трудно, посмотрите, где может скрываться эта ошибка :)
Вроде все просто и на скорость передачи здесь ничего влиять не должно?

Const
 cDelitel : String = "#end#";


procedure ClientDataProc(Socket:TCustomWinSocket; s:string);
begin
if Copy(s,1,2) = "#M" then begin
 Delete(s,1,2);
 ChatMemo.Lines.Add("["+TimeToStr(Time)+"]  "+ Copy(s,1,Pos(";",s)-1)+"> "+
           Copy( s, Pos(";",s)+1, Length(s)-Pos(";",s) ) );
 Exit;
end;
end;

procedure TfrmMy.sClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
var
 s : string;
 i : integer;
begin
 s:=Socket.ReceiveText; // присваиваем s полученную строку из Socket
 if ClientBuf<>""
   then ClientBuf := ClientBuf+s  // в буфере был кусок какой-то стороки
   else ClientBuf := s;
 i:=0;
 repeat // разделяем строку, если одновременно пришло несколько
   i:=Pos(cDelitel,ClientBuf);   // ищем раздлелитель строк в буфере
   if i<>0 then begin   // найден разделитель строк
     s:=Copy(ClientBuf,1,i-1); // копируем одну пришедшую строку в s
     Delete(ClientBuf,1,i+Length(cDelitel)-1); // удаляем из буфера уже скопированную строку
     ClientDataProc(sClientSocket.Socket,s) // обрабатываем выделенную строку
   end;
 until i=0; // повторять, пока будет не найден разделитель строк
end;

procedure TfrmMy.TextEditKeyDown(Sender: TObject; var Key: Word;
         Shift: TShiftState);
var
 s:  string;
 i:  integer;
begin
 if Key = VK_RETURN then begin  // нажата клавиша Enter
   s := "#M"+NickName+";"+TextEdit.Text; // Добавляем наше имя (от кого) и само сообщение
   If sServerSocket.Active=True then  // проверка, в каком режиме находится программа
     For i:=0 to sServerSocket.Socket.ActiveConnections-1 do  // отправляем сообщение с сервера всем пользователям
       sServerSocket.Socket.Connections[i].SendText(s)
   else  // отправляем сообщение с клиента
     sClientSocket.Socket.SendText(s);
   TextEdit.Clear;  // очищаем TextEdit
 end;
 ActiveControl := TextEdit;
end;

procedure TfrmMy.sServerSocketClientRead(Sender: TObject;
         Socket: TCustomWinSocket);
var
 i     : Integer;
begin
 if Copy(s,1,2) = "#M" then begin  // обработка сервером
   for i := 0 to sServerSocket.Socket.ActiveConnections-1 do
     sServerSocket.Socket.Connections[i].SendText(s+cDelitel);
   Exit;
 end;
end;


 
Сергей М. ©   (2008-11-01 15:41) [9]

Явных несуразностей пока не видно, хотя код и требует некоторых довольно важных доработок/переработок.

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

http://www.google.ru/search?hl=ru&newwindow=1&client=firefox-a&rls=org.mozilla%3Aru%3Aofficial&hs=6Gv&q=Nagle+SetSockOpt++TCP_NODELAY&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=lang_ru&aq=f&oq=


 
Андрей   (2008-11-01 16:13) [10]

Почитаю на досуге, попробую разобраться :)
А что за
>  довольно важных доработок/переработок

требует код? Просветите, пожалуйста.


 
Сергей М. ©   (2008-11-01 16:59) [11]


> Просветите, пожалуйста.


Вот тебе информация к размышлению на досуге :

SendText - это функциональный метод, он возвращает результат, от значения которого напрямую зависит дальнейшее ветвление правильного алгоритма.

Ты этот результат игнорируешь, следовательно, в произвольных "боевых" условиях твой алгоритм рано или поздно даст сбой.


 
Андрей   (2008-11-01 23:06) [12]

Вставил на сервере и клиенте в обработку приема и отсылки сообщений
вывод на экран TimeToStr(Time):
Задержка происходит на сервере между приемом строки и отправкой ее по клиентам.
Вопрос - почему и как это победить? Если это алгоритм Нагеля, то как его отключить в Делфи?

procedure TfrmMy.sServerSocketClientRead(Sender: TObject;
        Socket: TCustomWinSocket);
var
i     : Integer;
begin
s:=Socket.ReceiveText;
Memo1.Lines.Add("["+TimeToStr(Time)+"]  получил сообщение от клиента: "+s);
if Copy(s,1,2) = "#M" then begin  // обработка сервером
  for i := 0 to sServerSocket.Socket.ActiveConnections-1 do
    sServerSocket.Socket.Connections[i].SendText(s+cDelitel);
  Memo1.Lines.Add("["+TimeToStr(Time)+"]  рассылаю сообщения клиентам ");
  Exit;
end;
end;


 
Андрей   (2008-11-01 23:34) [13]

Если опция TCP_NODELAY установлена с помощью setsockopt, то она действует в пределах только указанного сокета или это глобальное изменение настроек конкретного компа для работы с сетью?


 
Андрей   (2008-11-02 00:03) [14]

Похоже глупость сморозил в предыдущем вопросе :) . Где можно почитать про все параметры setsockopt? Желательно на русском, но можно и на английском, если на русском нет :)


 
Андрей   (2008-11-02 14:54) [15]


procedure Tfrm1.sServerSocketClientRead(Sender: TObject;
         Socket: TCustomWinSocket);
var
 s, from_, to_, color_, time_, temp_ : string;
 game_   : string[8];
 i,j     : Integer;
begin
 Memo1.Lines.Add("["+TimeToStr(Time)+"] handle="+IntToStr(Socket.SocketHandle));
 j:=sizeof(i);
 GetSockOpt(Socket.SocketHandle,SOL_SOCKET,SO_SNDBUF,@i,j);
 Memo1.Lines.Add("["+TimeToStr(Time)+"] SO_SNDBUF="+IntToStr(i));
 GetSockOpt(Socket.SocketHandle,IPPROTO_TCP,TCP_NODELAY,@i,j);
 Memo1.Lines.Add("["+TimeToStr(Time)+"] NO_DELAY установлен и ="+IntToStr(i));
 s := Socket.ReceiveText;
 Memo1.Lines.Add("["+TimeToStr(Time)+"]  получил сообщение от клиента: "+s);

if (Copy(s,1,2) = "#M")then begin
   Memo1.Lines.Add("["+TimeToStr(Time)+"] вошли в процедуру #M");
   for i := 0 to sServerSocket.Socket.ActiveConnections-1 do
     sServerSocket.Socket.Connections[i].SendText(s+cDelitel);
   Delete(s,1,2);
   Memo1.Lines.Add("["+TimeToStr(Time)+"]  рассылаю сообщения клиентам "+ Copy(s,1,Pos(";",s)-1)+"> "+Copy( s, Pos(";",s)+1, Length(s)-Pos(";",s) ) );
   Exit;
 end;

end;

procedure Tfrm1.sServerSocketGetSocket(Sender: TObject; Socket: Integer;
 var ClientSocket: TServerClientWinSocket);
var
 i, len : integer;
begin
 len:=sizeof(i);
 i:=0;
 SetSockOpt(Socket,SOL_SOCKET,SO_SNDBUF,@i,len);
 i:=1;
 SetSockOpt(Socket,IPPROTO_TCP,TCP_NODELAY,@i,sizeof(i));
end;


в результате получаю
на сервере:

[14:33:11] handle=272
[14:33:11] SO_SNDBUF=0
[14:33:11] NO_DELAY установлен и =1
здесь идет задержка и потом вываливаются сразу оставшиеся строки
[14:33:11]  получил сообщение от клиента: #Mпервое сообщение      
[14:33:15] вошли в процедуру #M
[14:33:15]  рассылаю сообщения клиентам> первое сообщение

у клиента:

[14:33:11]  посылаю сообщение на сервер: первое сообщение
[14:33:11]  отослал
[14:33:15]  получил сообщение от сервера: #Mпервое сообщение#end#
[14:33:15] сообщение с сервера после оработки>первое сообщение


Т.е. буфер отсылки сокета обнулен, TCP_NODELAY отключена, а задержка на сервере между ReceiveText и отсылкой по клиентам составляет 4с
У меня уже мозги скоро закипят :) помогите, плиз, укажите, где у меня ошибка.


 
Сергей М. ©   (2008-11-02 18:05) [16]

Отключать алгоритм Нагеля и на стороне клиента и на стороне сервера следует сразу после установки соединения.


 
Сергей М. ©   (2008-11-02 18:10) [17]


>  i:=0;
>  SetSockOpt(Socket,SOL_SOCKET,SO_SNDBUF,@i,len);


Это лишнее


 
Андрей   (2008-11-02 19:25) [18]


> Отключать алгоритм Нагеля и на стороне клиента и на стороне
> сервера следует сразу после установки соединения.

Так со стороны клиента, вроде, никаких задержек нет. Сервер начинает обрабатыват событие OnClientRead в ту же секунду, в какую клиент отсылает сообщение. Задержка начинается при попытке прочесть данные с помощью ReceiveText. Как раз между первым и вторым выводом в Memo сообщения.

Memo1.Lines.Add("["+TimeToStr(Time)+"] NO_DELAY установлен и ="+IntToStr(i));
// здесь секунды клиента и сервера совпадают
s := Socket.ReceiveText;
// а здесь уже разница в 4-5с
Memo1.Lines.Add("["+TimeToStr(Time)+"]  получил сообщение от клиента: "+s);

Вставил отключение Нагеля на событие ClientSocketConnect результат тот же :(

И еще одна странность: вижу, что после начала выполнения оператора  ReceiveText идет фактическая задержка, однако строки

[14:33:11]  получил сообщение от клиента: #Mпервое сообщение      
[14:33:15] вошли в процедуру #M

вываливаются одновременно в [14:33:15]


> SetSockOpt(Socket,SOL_SOCKET,SO_SNDBUF,@i,len);

это я вставил на всякий случай, т.к. везде (где я нашел описания параметров сокета) сказано, что, если буфер отправки будет = 0, то кэшироваться сообщения не будут, а будут отправляться сразу.


 
Сергей М. ©   (2008-11-02 20:58) [19]

Не верю.

ReceiveText в контексте этого обработчика должна выполниться практически мгновенно.


 
Андрей   (2008-11-02 21:11) [20]

Вот ... :(
3 дня промучался. Сейчас ради эксперимента убрал на сервере
s := Socket.ReceiveText; и вставил его в отображение Memo.
Откликнулся мгновенно. Поставил эту строку назад и все летает.
Что было так и не понял. Наверное, какой-то глюк.
Завтра тестить буду. Спасибо за отклики.


 
Тын-Дын ©   (2008-11-06 19:45) [21]

Сомнения вызывает код чтения пришедших данных.
Более того - в нём ошибка.
Правильный алгоритм такой:

var
 s: String;
begin
 s := "";
 while Socket.ReceiveLength>0 do s := s+Socket.ReceiveText;
...


 
Сергей М. ©   (2008-11-06 20:11) [22]


> в нём ошибка


Нет в нем в этом смысле ошибки.
Данные не потеряются, так что цикл вовсе не обязателен.


 
Тын-Дын ©   (2008-11-06 20:21) [23]


> Сергей М. ©   (06.11.08 20:11) [22]
>
> > в нём ошибка
>
>
> Нет в нем в этом смысле ошибки.
> Данные не потеряются, так что цикл вовсе не обязателен.


Судя по постам выше, у автора на это может быть логика завязана.


 
Сергей М. ©   (2008-11-06 20:28) [24]

Логика хоть и неважнецкая, но с этим все в порядке - получил шматок текста, дописал в конец стат.буфера, тут же обработал тек.содержимое буфера с должной его коррекцией (если таковая требуется) после обработки.


 
Тын-Дын ©   (2008-11-06 20:35) [25]


> Андрей   (29.10.08 14:36)  


А на какой операционной системе проверяешь?


 
Сергей М. ©   (2008-11-06 21:04) [26]


> Тын-Дын ©   (06.11.08 20:35) [25]


А по барабану на какой.

WSA 1.01 работает везде одинаково



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2010.09.05;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.004 c
15-1276185441
da4
2010-06-10 19:57
2010.09.05
Кто сильнее, Тигр Лев или Медведь?


2-1276185461
Artemon
2010-06-10 19:57
2010.09.05
Вывод времени в QRDBText


2-1276061538
Delphist2
2010-06-09 09:32
2010.09.05
работа с excel


4-1239652712
Unlocker
2009-04-13 23:58
2010.09.05
Запуск под админом


4-1239772550
SPeller
2009-04-15 09:15
2010.09.05
Как достоверно определить что программа запущена как сервис?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский