Форум: "Сети";
Текущий архив: 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