-
Уважаемые, не подскажете, от чего может зависеть скорость передачи/приема пакетов? При тесте на локальной машине все летает, а как только подключаю в локальную сеть, так начинаются задержки отправки/приема (приложение работает по принципу: клиент отослал на сервер пакет, тот его разослал всем подключившимся, в том числе и тому, кто отослал). На сеть грешить сложно, т.к. обычные чаты в ней работают практически без задержек. Есть различие в скорости на чем делать клиента/сервер синхронный/асинхронный режимы?
-
> начинаются задержки отправки/приема
В чем и как это выражается ?
> Есть различие в скорости на чем делать клиента/сервер синхронный/асинхронный > режимы?
Принципиальных различий нет.
-
> тот его разослал всем подключившимся
Если сервер однопоточный, то при росте числа активных клиентов рост задержки будет неминуем.
-
> клиент отослал на сервер пакет, тот его разослал всем подключившимся, > в том числе и тому, кто отослал)
Так правильно, ты сеть по геометрической прогрессии загружаешь. Каждый подключённый клиент это увеличение трафика на КолКлиентов*2. И Если ты работаешь не по UDP - начнуться проблемы.
> Принципиальных различий нет.
Огромные ! Асинхронный режим это чисто придумка MS - там прослойка (не спорю написана хорошо) над чисто синхронными сокетами.
-
> tesseract © (29.10.08 20:04) [3]
> Огромные
Да не трынди)
> Асинхронный режим это чисто придумка MS
Ты не любишь кошек ? Ну тогда и не советуй как их готовить !)
-
> tesseract © (29.10.08 20:04) [3]
Извини за резкость
-
>В чем и как это выражается?
Подключены 2 клиента. Задержка между отправкой пакета и приходом его же отправляющему клиенту несколько секунд.
-
> Андрей (31.10.08 20:28) [6]
Думаю что у тебя ошибка в программе.
-
Если не трудно, посмотрите, где может скрываться эта ошибка :) Вроде все просто и на скорость передачи здесь ничего влиять не должно?
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; 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); 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 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; 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;
-
-
Почитаю на досуге, попробую разобраться :) А что за > довольно важных доработок/переработок
требует код? Просветите, пожалуйста.
-
> Просветите, пожалуйста.
Вот тебе информация к размышлению на досуге :
SendText - это функциональный метод, он возвращает результат, от значения которого напрямую зависит дальнейшее ветвление правильного алгоритма.
Ты этот результат игнорируешь, следовательно, в произвольных "боевых" условиях твой алгоритм рано или поздно даст сбой.
-
Вставил на сервере и клиенте в обработку приема и отсылки сообщений вывод на экран 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;
-
Если опция TCP_NODELAY установлена с помощью setsockopt, то она действует в пределах только указанного сокета или это глобальное изменение настроек конкретного компа для работы с сетью?
-
Похоже глупость сморозил в предыдущем вопросе :) . Где можно почитать про все параметры setsockopt? Желательно на русском, но можно и на английском, если на русском нет :)
-
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с У меня уже мозги скоро закипят :) помогите, плиз, укажите, где у меня ошибка.
-
Отключать алгоритм Нагеля и на стороне клиента и на стороне сервера следует сразу после установки соединения.
-
> i:=0; > SetSockOpt(Socket,SOL_SOCKET,SO_SNDBUF,@i,len);
Это лишнее
-
> Отключать алгоритм Нагеля и на стороне клиента и на стороне > сервера следует сразу после установки соединения.
Так со стороны клиента, вроде, никаких задержек нет. Сервер начинает обрабатыват событие OnClientRead в ту же секунду, в какую клиент отсылает сообщение. Задержка начинается при попытке прочесть данные с помощью ReceiveText. Как раз между первым и вторым выводом в Memo сообщения.
Memo1.Lines.Add('['+TimeToStr(Time)+'] NO_DELAY установлен и ='+IntToStr(i));
s := Socket.ReceiveText;
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, то кэшироваться сообщения не будут, а будут отправляться сразу.
-
Не верю.
ReceiveText в контексте этого обработчика должна выполниться практически мгновенно.
-
Вот ... :( 3 дня промучался. Сейчас ради эксперимента убрал на сервере s := Socket.ReceiveText; и вставил его в отображение Memo. Откликнулся мгновенно. Поставил эту строку назад и все летает. Что было так и не понял. Наверное, какой-то глюк. Завтра тестить буду. Спасибо за отклики.
-
Сомнения вызывает код чтения пришедших данных. Более того - в нём ошибка. Правильный алгоритм такой: var
s: String;
begin
s := '';
while Socket.ReceiveLength>0 do s := s+Socket.ReceiveText;
...
-
> в нём ошибка
Нет в нем в этом смысле ошибки. Данные не потеряются, так что цикл вовсе не обязателен.
-
> Сергей М. © (06.11.08 20:11) [22] > > > в нём ошибка > > > Нет в нем в этом смысле ошибки. > Данные не потеряются, так что цикл вовсе не обязателен.
Судя по постам выше, у автора на это может быть логика завязана.
-
Логика хоть и неважнецкая, но с этим все в порядке - получил шматок текста, дописал в конец стат.буфера, тут же обработал тек.содержимое буфера с должной его коррекцией (если таковая требуется) после обработки.
-
> Андрей (29.10.08 14:36)
А на какой операционной системе проверяешь?
-
> Тын-Дын © (06.11.08 20:35) [25]
А по барабану на какой.
WSA 1.01 работает везде одинаково
|