Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.103 c
15-1265387354
Jeer
2010-02-05 19:29
2010.08.27
arduino + clone


15-1265367565
unmazable
2010-02-05 13:59
2010.08.27
Создание интерпритатора(компилятора)


2-1267000689
AlexAA
2010-02-24 11:38
2010.08.27
Событие "AfterOpen" в TDBGrid


8-1196327132
DimaTS
2007-11-29 12:05
2010.08.27
Надпись вдоль кривой (например по окружности)


2-1274132876
antonn
2010-05-18 01:47
2010.08.27
Дата компилирования





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский