Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
ВнизTCPClient вторая посылка не проходит Найти похожие ветки
← →
novichek (2010-05-11 22:29) [0]клиент:
if TcpClient1.Connected then TcpClient1.Sendln(edit2.Text);
сервер:
procedure TForm1.TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
begin
edit1.Text:= ClientSocket.Receiveln;
end;
первая отправка строки доходит до сервера, последующте нет, хотя connected клиента True.
добавил:
TcpClient1.Sendln(edit2.Text);
TcpClient1.Disconnect;
TcpClient1.Connect;
стало работать, но это херня рвать установленную связь..
помогите с решением, необходимо один раз законнектится с сервером и в дальнейшем независимо клиент серверу и сервер клиенту что бы могли отправлять сообщения в виде строк...
пока рука не поднимается пробывать на сокетах писать, если готовое решение не могу использовать...
← →
Сергей М. © (2010-05-11 22:37) [1]Если ты лепишь чат, то следует отключать алгоритм Нагеля.
По умолчанию он включен.
← →
novichek (2010-05-11 23:02) [2]не могли бы вы уточнить, на каком этапе отключать?
на событии connect"а клиента ?
procedure TForm1.TcpClient1Connect(Sender: TObject);
begin
setsockopt(socked, IPPROTO_IP, TCP_NODELAY, 0, 1); // так ?
end;
только как тут socked вытянуть не могу понять ))
вообще-то я не чат пишу..
просто нужно организовать общение клиентов с сервером путем передачи строк.
← →
Сергей М. © (2010-05-11 23:11) [3]
> на событии connect"а клиента ?
Да.
> как тут socked вытянуть
TTCPClient(Sender).Handle
> я не чат пишу
Не суть как важно.
← →
novichek (2010-05-11 23:31) [4]procedure TForm1.TcpClient1Connect(Sender: TObject);
begin
setsockopt(TTCPClient(Sender).Handle, IPPROTO_IP, TCP_NODELAY, 0, 1);
end;
всё равно вторая посылка не проходит...
решил попытать счаcтья на инди (d2007)
var
myContext: TIdContext;
...
// отправка серверу
procedure TForm1.Button1Click(Sender: TObject);
begin
if IdTCPClient1.Connected then IdTCPClient1.IOHandler.WriteLn(TimeToStr(time));
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
myContext:= AContext; // сохранил
edit1.Text:= AContext.Connection.IOHandler.ReadLn; // прочитал что пришло
end;
теперь пытаюсь со стороны сервера отправить
procedure TForm1.Button2Click(Sender: TObject);
begin
myContext.Connection.IOHandler.WriteLn(TimeToStr(time));
end;
на клиенте обрабатываю пиём так:
procedure TForm1.IdTCPClient1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
begin
if AWorkMode = wmRead then begin
edit2.Text:= "принял";
end;
end;
1) тут не знаю как добраться до входящего буфера\текста
2) один фиг, ставил бряк - управление не приходит
подскажите пожалуйста где торможу..
← →
Сергей М. © (2010-05-11 23:34) [5]
> всё равно вторая посылка не проходит.
Значит у тебя ошибка в программе.
← →
novichek (2010-05-11 23:43) [6]хм.. там кода пару строк:
procedure TForm1.FormCreate(Sender: TObject);
begin
TcpServer1.BlockMode:= bmThreadBlocking;
TcpClient1.BlockMode:= bmBlocking;
TcpServer1.Active:= true;
TcpClient1.Active:= true;
TcpClient1.Connect;
end;
procedure TForm1.TcpClient1Connect(Sender: TObject);
begin
setsockopt(TTCPClient(Sender).Handle, IPPROTO_IP, TCP_NODELAY, 0, 1);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if TcpClient1.Connected then begin
TcpClient1.Sendln(edit2.Text);
// TcpClient1.Disconnect;
// TcpClient1.Connect;
end;
end;
procedure TForm1.TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
begin
edit1.Text:= ClientSocket.Receiveln;
end;
← →
novichek (2010-05-11 23:50) [7]стало ещё интересней..
procedure TForm1.TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
var
s: String;
begin
s:= ClientSocket.Receiveln;
while s<>"" do begin
edit1.Text:= edit1.Text + s;
s:= ClientSocket.Receiveln;
end;
end.
стало теперь принимать и последующие отправки и без setsockopt..
← →
Сергей М. © (2010-05-11 23:53) [8]Ну вот тебе и ошибка - по завершению обработки события OnAccept сервер разрывает соединение с клиентом.
Это абсолютно нормальное поведение TTCPServer"а.
← →
novichek (2010-05-11 23:54) [9]не подскажите как теперь передать от серверка данные клиенту..
пробую так:
procedure TForm1.Button1Click(Sender: TObject);
begin
TcpServer1.Sendln(timeToStr(time));
end;
procedure TForm1.TcpServer1Accept(Sender: TObject; ClientSocket: TCustomIpClient);
var
s: String;
begin
s:= ClientSocket.Receiveln;
while s<>"" do begin
edit1.Text:= edit1.Text + s;
s:= ClientSocket.Receiveln;
end;
ClientSocket.Sendln(timeToStr(time));
end;
у клиента обрабатываю
procedure TForm1.TcpClient1Receive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
begin
ShowMessage("получил");
end;
ничего не приходит..
← →
Сергей М. © (2010-05-11 23:55) [10]
> стало теперь принимать и ..без setsockopt.
Как только ты разнесешь своих клиента и сервера по разным углам Тырнета, грабли со включенным алгоритмом Нагля обязательно хлобыстнут)
← →
novichek (2010-05-11 23:55) [11]Сергей М., так в том то и дело что не разрывает..
наверное из-за того что не всё вычитаваю, следующие событие TcpServer1Accept не приходит
← →
novichek (2010-05-12 00:09) [12]ой да, после завершения TcpServer1Accept разрывает коннект сервер..
а можео как-то это отменить?
и странно что клиент показывает connected - true и пытается посылать не вызывая исключения..
или в обработчике TcpServer1Accept можно ли на цикл повесить Receiveln, тем самым не давая оборвать соединение и ждать очередных данных? правильно ли это будет?
ну и так же с отправкой от сервера клиенту ничего не получается..
← →
Сергей М. © (2010-05-12 00:14) [13]> в том то и дело что не разрывает.
Разрывает, даже не сомневайся.
> следующие событие TcpServer1Accept не приходит
А с какого перепугу оно должно возникнуть повторно, если клиент законнектился всего один раз ?
← →
Сергей М. © (2010-05-12 00:18) [14]
> можео как-то это отменить
А зачем ? Так задумано разработчиком.
> странно что клиент показывает connected - true и пытается
> посылать не вызывая исключения
Оно и не должно возникакть - на то есть событие OnError
> в обработчике TcpServer1Accept можно ли на цикл повесить
Именно так.
> с отправкой от сервера клиенту ничего не получается
Значит у тебя ошибка.
← →
novichek (2010-05-12 01:04) [15]наверное нужно на клиенте так же вешать TcpClient1.Receiveln..
но тогда если клиент будет ждать прием а нужно будет что-то опять отправить..
как-то всё заумно сделано..
логичнее было бы просто после установления соединения события работали отдельно на прием и передачу.. закрывать соединение по команде.
← →
Германн © (2010-05-12 01:41) [16]
> как-то всё заумно сделано..
Дозволено ли мне будет скромно предложить обратить внимание на ICS
http://www.overbyte.be/frame_index.html
?
← →
Вариант (2010-05-12 06:44) [17]
> Сергей М. © (11.05.10 23:55) [10]
> Как только ты разнесешь своих клиента и сервера по разным
> углам Тырнета, грабли со включенным алгоритмом Нагля обязательно
> хлобыстнут)
А какие грабли? Насколько я читал , алгоритм Nagla как раз предназначен для решения проблем по "углам тырнета", для оптимизации нагрузки сети, в том числе для решения проблем "малых" пакетов.
← →
Вариант (2010-05-12 07:10) [18]
> novichek (11.05.10 23:31) [4]
> setsockopt(TTCPClient(Sender).Handle, IPPROTO_IP, TCP_NODELAY,
> 0, 1)
Это кстати включает алгоритм Nagla - по умолчанию он и так включен
← →
Вариант (2010-05-12 09:02) [19]
> novichek (11.05.10 23:31) [4]
> setsockopt(TTCPClient(Sender).Handle, IPPROTO_IP, TCP_NODELAY,
> 0, 1)
И еще раз возвращаясь - код неверный, ибо выделенное жирыным должно быть не значением, а указателем
← →
Сергей М. © (2010-05-12 11:59) [20]
> тогда если клиент будет ждать прием а нужно будет что-то
> опять отправить.
На то есть метод WaitForData()
> как-то всё заумно сделано
Нормально сделано.
← →
Сергей М. © (2010-05-12 12:03) [21]
> Вариант (12.05.10 06:44) [17]
Об "оптимизации нагрузки" речь не идет.
Речь идет о буферизации формируемых потоков сетевого вывода, которой Нагль заправляет из соображений той самой оптимизвции.
А буферизация вносит задержку.
А сообщение нужно доставить насколько возможно быстрее, хоть маленькое хоть большое.
А Наглю это фиолетово - он занят оптимизацией и ему нет дела до "срочности" доставки.
← →
Вариант (2010-05-12 13:09) [22]
> Сергей М. © (12.05.10 12:03) [21]
Задержка есть, но это не грабли.
В RFC 896 дается примерная прикидка, насколько будет большой такая задержка - фактически это время движения пакета до удаленного хоста +подтверждение пакета удаленным хостом, если есть неподтвержденные пакеты. Если таковых пакетов нет, то задержка 0. При работе в интернете, при сильной загрузке сети много мелких пакетов могут так же иметь задержку в доставке из-за перегрузки канала и даже большую. При больших пакетах, имеющих размер больше окна передачи буферизация произойдет независимо от того, включен алгоритм или нет. Поэтому я склонен при работе в интернете по крайней мере придерживаться рекомендаций, в том числе и из MSDN
> Application writers should not set TCP_NODELAY unless the
> impact of doing so is well-understood and desired because
> setting TCP_NODELAY can have a significant negative impact
> on network and application performance
ТО есть резюмируя - маленькая задержка приводит в итоге к росту производительности сети и приложения. Впрочем в локальной сети допускается выключение данного алгоритма, так как локальная сеть успевает справляться с лишней нагрузкой вызванной проблемой "маленьких пакетов".
← →
novichek (2010-05-12 13:58) [23]простите, так правильно ? :
var
b: byte;
..
b:= 0;
setsockopt(TTCPClient(Sender).Handle, IPPROTO_IP, TCP_NODELAY, pointer(b), 1)
← →
Вариант (2010-05-12 14:16) [24]var
b:bool;
d:DWORD;
i:integer;
begin
b:=true;// Выключасет алгоритм Nagla, а false включает
I:=setsockopt(SocketHandle, IPPROTO_TCP, TCP_NODELAY,@b, sizeof(bool));
if i <> 0 then
begin
d:=WsaGetLastError;
// как-то реагируем на ошибку
end;
end;
← →
novichek (2010-05-12 22:50) [25]спасибо большое за разъяснения, картина почти вырисовалась!
осталось только уточнить, пакеты мелкие, около 10 байт, но летать будут часто по обычной внутренней сетке.
так и не понял, стоит ли включать этот алгоритм Nagla или нет?
и второй вопрос насчет хоста.
если у меня на компе 3 айпи адреса, при иницилизации сервера я не указываю ему TcpServer.LocalHost а только назначаю порт. он где будет слушать порт?
← →
Вариант (2010-05-13 06:20) [26]
> novichek (12.05.10 22:50) [25]
По моему мнению ( смотрим RFC 896 часть The solution to the small-packet problem) для локаоной сети это не так важно-
> "With our scheme, every character the user types will
> find TCP with an idle connection, and the character will
> be sent
> at once, just as in the no-control case. The user will
> see no
> visible delay. Thus, our scheme performs as well as
> the no-
> control scheme and provides better responsiveness than the
> timer
> scheme."
- где под
> With our scheme
- подразумевался алгоритм Nagle. Кратко об английском тексте - Можешь включить, можешь выключить, время отклика сети маленькое и пакеты будут отправляться быстро, практически одинаково что для схемы с алгоритмом, что для схемы без без него.
А лучший критерий - практика и свой собственный опыт. Проведи эксперимент и если заметишь разницу - выбери более подходящее для тебя вариант.
← →
Вариант (2010-05-13 06:42) [27]
> novichek (12.05.10 22:50) [25]
> и второй вопрос насчет хоста.
> если у меня на компе 3 айпи адреса, при иницилизации сервера
> я не указываю ему TcpServer.LocalHost а только назначаю
> порт. он где будет слушать порт?
На всех адресах
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.108 c