Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.09.05;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.011 c
2-1276051988
zergost
2010-06-09 06:53
2010.09.05
создания полей таблиц


2-1276170937
linox
2010-06-10 15:55
2010.09.05
ADO ACCESS связанные таблицы просмотр инфо


15-1276193680
AKE
2010-06-10 22:14
2010.09.05
Я забыл можно ли объявлять функцию внутри функции?


2-1275975584
программер
2010-06-08 09:39
2010.09.05
500 пикселей размесить в формате 4:3


15-1276031254
Юрий Зотов
2010-06-09 01:07
2010.09.05
Кто знает Висту и семерку - нужна консультация