Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];

Вниз

Как реализовать чтоб сервре и клиент слушали порт?   Найти похожие ветки 

 
h0use   (2003-11-25 17:14) [0]

Есть сервак, у которого в методе OnExecute

procedure TFM.TCPServerExecute(AThread: TIdPeerThread);
var
AMsg : TCommBlock;
Msg : String;
begin
if not AThread.Terminated and AThread.Connection.Connected then
try
Msg:=AThread.Connection.ReadLn;
if Msg="" then exit;
AThread.Connection.ReadBuffer(AMsg,SizeOf(AMsg));
ShowMessage(IntToStr(AMsg.Command)+IntToStr(AMsg.Argument1)+IntToStr(AMsg.Argument2)+AMsg.Msg);
case AMsg.Command of //
cmdLogin : ServerLogin(AMsg,AThread);
cmdLogout : ServerLogout(AMsg,AThread);
cmdCommand: ServerCommand(AMsg,AThread);
cmdSQL : ServerSQL(AMsg,AThread);
cmdMessage: ServerChat(AMsg,AThread);
end; // case
except
on E: Exception do
SaveLog(0,3,"Socket read error: " + e.Message);
end;
end; // TCPServerExecute

Работает и сам сервак не виснет, но в клиенте в процедуре

procedure TfmMain.TimerTimer(Sender: TObject);
var
AMsg: TCommBlock;
Msg : String;
begin
if (not TCPClient.Connected) then exit;
try
Msg:=TCPClient.ReadLn(#10,50); <------------- Вот здесь висим после первого обмена информацией
if Msg="<<<" then
begin
TCPClient.ReadBuffer(AMsg,SizeOf(AMsg));
case AMsg.Command of //
cmdLogin : ClientConnect(AMsg);
cmdLogout: ClientDisconnect(AMsg);
end; // case
end;
except
on e: Exception do
ShowMessage(e.Message);
end; // try/except
Application.ProcessMessages;
end;


Как сделать так, чтоб клиент при ожидании какой-либо инфы от сервера не вис?


 
Digitman   (2003-11-25 17:20) [1]

из кода совершенно непонятно, кто из них, в соответствии с твоим протоколом инф.обмена, первый должен "говорить", а кто "слушать"

оба сразу "слушают" и ждут неизвестно чего


 
h0use   (2003-11-25 17:22) [2]

А как сделать так чтоб клиент не вис, пока сервер думает что ему(клиенту) отправить?


 
Digitman   (2003-11-25 17:33) [3]

а где утебя сервер что-то "думает", а потом "отправляет" ?

я вот вижу, что первым делом сервер ждет чего-то от клиента

Msg:=AThread.Connection.ReadLn;

а клиент в это же время ждет чего-то от сервера

Msg:=TCPClient.ReadLn(#10,50)

)))

и тишина гробовая стоит поэтому)


 
h0use   (2003-11-25 17:36) [4]

У меня сервер реагирует на сообщения от клиента и в соотв. процедурах ему отправляет что-то. Например нужно сделать как чат, как только один пользователь послал мессагу, сервре ее перенаправил другому пользователю, поэтому у меня и сервер слушает и клиент.


 
h0use   (2003-11-25 17:52) [5]

Неужели это нереальная задача для Инди?


 
Digitman   (2003-11-25 18:17) [6]


> У меня сервер реагирует на сообщения от клиента


а где в твоем коде клиент ХОТЬ ЧТО-ЛИБО посылает серверу ?!


> Неужели это нереальная задача для Инди?


при чем здесь инди ? Совершенно ни при чем ! Это лишь - одна из оболочек транспортного механизма, не более того


 
h0use   (2003-11-26 09:40) [7]

Клиент серверу отсылает сообщения в ответ на сообщения от сервера и наоборот. Но в промежутке когда и сревре и клиент ничего не делают, сообщений нет, можно конечно чтоб они занимались "пинг-понгом", но неужели нельзя сделать так чтоб при простое клиент мог работать, при этом в любой момент ожидать сообщение от сервера.


 
Reindeer Moss Eater   (2003-11-26 09:44) [8]

Какой смысл ты вкладываешь в термины "клиент не работает" "клиент мог работать"?

Он у тебя что, аварийно завершает свой процесс и выгружается из памяти?


 
Digitman   (2003-11-26 09:48) [9]


> неужели нельзя сделать так чтоб при простое клиент мог работать,
> при этом в любой момент ожидать сообщение от сервера.


в кл.приложении организуй доп.код.поток
пусть в нем происходит коннект к серверу и ожидание сообщений от него

в тоже время осн.код.поток параллельно может заниматься всем чем угодно


 
Digitman   (2003-11-26 09:50) [10]


> Reindeer Moss Eater


клиент у него "виснет" на первом же блокирующем ReadLn() в обработчике таймера (нахрена там таймер ? ума не приложу)


 
Reindeer Moss Eater   (2003-11-26 10:12) [11]

Это "пунктик" такой есть.
Если надо что-то сделать несколько раз, то без таймера ну никак.
А уж если приложение консольное, и таймер некуда "кинуть", то вообще засада, задача для ктн, как минимум.
:)


 
Reindeer Moss Eater   (2003-11-26 10:18) [12]

TidAntifreeze.

Занимается обработкой сообщений во время синхронных вызовов.


 
h0use   (2003-11-26 10:24) [13]

А подробней?


 
Reindeer Moss Eater   (2003-11-26 10:36) [14]

Ты уже попробовал изпользовать TidAntifreeze?


 
h0use   (2003-11-26 10:42) [15]

Нет, я не нашел примера, а просто кидать его на форму не приводит к каим либо изменениям, потом вообще не понятно куда его кидать, на сервер или клиент, или обоим сразу


 
Reindeer Moss Eater   (2003-11-26 11:31) [16]

"Кидать" его надо в GUI приложение.
Если синхронные методы библиотеки вызываются из главного потока приложения и если требуется обеспечить доступность UI во время работы.
Один экземпляр на все приложение.
Если свойство Active равно True, то пользовательский интерфейс не будет "засыпать" во время выполнения синхронных методов.


 
h0use   (2003-11-26 11:54) [17]

Это я понял, но, у меня даже при установке флага OnlyWhenIdle в False все равно прикладуха виснет :(


 
Reindeer Moss Eater   (2003-11-26 12:10) [18]

Код твоего клиента - одно сплошное недоразумение.
Таймер там что делает?


 
h0use   (2003-11-26 12:26) [19]

Как что, с периодичностью в секунду опрашивает порт, если там сообщения...


 
Reindeer Moss Eater   (2003-11-26 12:29) [20]

Замечательно.

Вызвали ReadLn первый раз.
Данных не пришло, возврата из метода пока нет,
тут срабатывает таймер, метод вызывается еще раз у того же самого экземпляра.
Данных не пришло, возврата из метода пока нет,
тут срабатывает таймер, метод вызывается еще раз у того же самого экземпляра.

Круто, правда?


 
Digitman   (2003-11-26 12:42) [21]


> Reindeer Moss Eater


> Данных не пришло, возврата из метода пока нет,
> тут срабатывает таймер, метод вызывается еще раз у того
> же самого экземпляра.


ты не загнул ли ?

imho, загнул явно
это ж все - осн.код.поток !

если сервер "молчит", то таймер "тикнет" всего один раз, и больше не дождется автор его "тиканий" - обработчик таймера-то "висит" на исполнении блокирующего ReadLn()...


 
h0use   (2003-11-26 12:43) [22]

А как сделать ПРАВИЛЬНО?


 
Digitman   (2003-11-26 12:44) [23]


> Reindeer Moss Eater


а-а-а ... ну если ты подразумеваешь инди-антифриз, то - да, это засада, конечно


 
Reindeer Moss Eater   (2003-11-26 12:47) [24]

ты не загнул ли ?

Сообщения-то все же обрабатываются благодаря антифризу.


 
h0use   (2003-11-26 12:48) [25]

Что самое интерсное, что пример я взял из демки самой Инди, она у меня тоже виснет. Но самое интерсное, что когда я использую Антифриз все замечательно работает до момента когда я хочу форму двинуть мышкой или например максимизировать.


 
Digitman   (2003-11-26 12:48) [26]


> h0use


я ж тебе сказал уже : транспорт (т.е. логику обращений к TCPClient"у) выноси в отдельный кодовый поток, а обработку данных, полученных с пом.транспорта, выполняй в другом (например - основном) код.потоке

что непонятного ?

убирай свои таймеры ! начерта они здесь не нужны)


 
h0use   (2003-11-26 12:51) [27]

Т.е. делать отдельный TThread где запускать TCPClienta, а данные sincronize с данными из форм?


 
Digitman   (2003-11-26 12:51) [28]


> Reindeer Moss Eater © (26.11.03 12:47) [24]


ну да, я уже вижу - ты эту ситуацию "замечательную" расписал именно в случае с антифризом

вообще-то дурь все это - все эти "антифризы", лучше не пользовать : нет прозрачности и наглядности собственной асинхр.логики


 
Reindeer Moss Eater   (2003-11-26 12:53) [29]

Лучше убери таймер и не надо вторичного потока.
Иначе запутаешься с потоком еще глубже чем сейчас


 
Digitman   (2003-11-26 12:56) [30]


> h0use © (26.11.03 12:51) [27]


при чем здесь "форма" ? трансп.поток синхронизировать нужно не с "формой", а с потоком, который будет обрабатывать поступающие из трансп.потока данные и/или передавать трансп.потоку данные, предназначенные для передачи их партнеру по инф.обмену


 
h0use   (2003-11-26 12:56) [31]

Хм, а как же тогда сервак слушать?


 
h0use   (2003-11-26 12:58) [32]


> при чем здесь "форма" ? трансп.поток синхронизировать нужно
> не с "формой", а с потоком, который будет обрабатывать поступающие
> из трансп.потока данные и/или передавать трансп.потоку данные,
> предназначенные для передачи их партнеру по инф.обмену

Все здорово, только нигде нет примера как на инди эти потоки реализовать, я сам так в начале хотел сделать, только не знаю каими методами можно разделить потоки на входящие и исходящие


 
h0use   (2003-11-26 13:01) [33]

пока у меня так

procedure TfmMain.ClientLogin;
var
AMsg: TCommBlock;
begin
try
Application.CreateForm(TPasswordDlg, PasswordDlg);
PasswordDlg.ShowModal;
if PasswordDlg.ModalResult=mrOK then
try
BAConn:=TSrvConn.Create;
BAConn.Host:="h0usexp";
BAConn.Port:=1000;
BAConn.User:=PasswordDlg.edLogin.Text;
BAConn.Password:=PasswordDlg.edPassword.Text;
TCPClient.Host:=BAConn.Host;
TCPCLient.Port:=BAConn.Port;
LogEvent.Active:=True;
TCPClient.Connect(10000);
AMsg.Command:=cmdLogin;
AMsg.Argument1:=argLoginClient;
if (BAConn.User<>"") and (BAConn.Password<>"")
then AMsg.Argument2:=optLoginHasInfo
else AMsg.Argument2:=optLoginNoInfo;
AMsg.Msg:=BAConn.User+"|"+BAConn.Password;
while true do
if TCPClient.Connected then
begin
SendMsg(AMsg);
break;
end;
ledConnected.Color:=clLime;
isConnected:=TCPClient.Connected;
btnConn.Hint:="


 
Digitman   (2003-11-26 13:14) [34]

убирай ты свой таймер, говорю тебе ! ни кселу ни к городу он здесь !

есть событие OnWork() , оно тебя известит о приходе некоторой порции данных от партнера, вот в его обработчике и считывай РЕАЛЬНО пришедшее от партнера кол-во байт данных


 
Reindeer Moss Eater   (2003-11-26 13:32) [35]

Скелет. Частный пример. Не образец для подражания.

const WM_SERVER_MSG = WM_USER + 101;

type
TForm1 = class(TForm)
IdTCPClient1: TIdTCPClient;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure SessionWithServer;
procedure OnServerMessage(var Msg : TMessage); message WM_SERVER_MSG;
public
{ Public declarations }
end;

implementation

{$R *.DFM}

type
PMyServerCmd = ^TMyServerCmd;
TMyServerCmd = record
sc_Cmd_Type : Word;
Param1,
Param2,
Param3 : string[30];
end;

var
SessionIsOver : boolean = False;

procedure TForm1.Button1Click(Sender: TObject);
begin
if ConnectClientToServerUsingIpAndPort("127.0.0.1",777) then
SessionWithServer;
end;

procedure TForm1.SessionWithServer;
var Cmd : TMyServerCmd;
begin
while not SessionIsOver do
try
IdTCPClient1.ReadBuffer(Cmd,SizeOf(Cmd));
SendMessage(Self.Handle,WM_SERVER_MSG,Integer(@Cmd),0);
except
Break;
end;
end;

procedure TForm1.OnServerMessage(var Msg: TMessage);
begin
case PMyServerCmd(Msg.WParam).sc_Cmd_Type of
1: begin
ShowMessage("Сервер требует сказать имя и пароль");
if ShowLoginDialog then
IdTCPClient1.WriteLn(UserName);
IdTCPClient1.WriteLn(Password);
end
3: ShowMessage("Делай то");
4: ShowMessage("Делай сё");
5: ShowMessage("Делай пятое");
6: ShowMessage("Делай десятое");
7: begin
ShowMessage("Нас отключают");
SessionIsOver:=True;
end;

end;
end;


 
h0use   (2003-11-26 13:40) [36]

Спраибо, до сообщений я не догадался, буду пробовать


 
Digitman   (2003-11-26 13:43) [37]

толку-то) ... теперь "висеть" будешь на строчке

IdTCPClient1.ReadBuffer(Cmd,SizeOf(Cmd))


 
h0use   (2003-11-26 13:46) [38]

С Антифризом не должно


 
Reindeer Moss Eater   (2003-11-26 13:46) [39]

Зато нам поверили, что таймер не нужен


 
Digitman   (2003-11-26 13:57) [40]


> Reindeer Moss Eater © (26.11.03 13:46) [39]


LOL


> h0use © (26.11.03 13:46) [38]


нафига ?! ну нафига тебе, скажи на милось, всякие таймеры да антифризы ? если есть событие OnWork(), АСИНХРОННО извещающее тебя о наступлении сетевого транспортного события а-ля "сервер ан сей момент прислал N байт, можно безо всяких задержек прочитать эти N байт из буфера и передать их на обработку куда-то" ?



Страницы: 1 2 вся ветка

Форум: "Сети";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.011 c
14-2346
klyonov
2004-01-13 16:37
2004.02.02
картинка


4-2421
Sanad
2003-11-21 08:24
2004.02.02
Перехват принтера


3-1960
alexEagle
2004-01-09 17:51
2004.02.02
TDBGrid.ReadOnly для Lookup ов???


1-2183
sbuffoon
2004-01-20 23:56
2004.02.02
Двигающаяся строка


1-2224
Goida
2004-01-20 15:50
2004.02.02
Рамка таблицы в Word.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский