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

Вниз

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

Наверх




Память: 0.55 MB
Время: 0.048 c
15-1270502764
Юзер
2010-04-06 01:26
2010.08.27
Польза от интернета :)


2-1275239628
Б
2010-05-30 21:13
2010.08.27
Редактор блок-схем.


3-1242282590
Sairex
2009-05-14 10:29
2010.08.27
Подскажите как узнать тип записи в DBF файле?


2-1273233990
Rolls
2010-05-07 16:06
2010.08.27
ListView вывод иконок


8-1205337835
Ramzes001
2008-03-12 19:03
2010.08.27
Запрет смены пропорций у фото