![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема с приложением клиент-сервер [D7, WinXP]
Colonel © (2008-09-01 21:17:00)Доброго всем времени суток,
подскажите в чем может быть проблема: пытаюсь сделать простое приложение клиент сервер, но не работает.
Вот код сервера:
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Active := True;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
j : integer;
begin
i := ServerSocket1.Socket.ReceiveText;
For j := 0 to ServerSocket1.Socket.ActiveConnections - 1 do
if ServerSocket1.Socket.Connections[j].SocketHandle Socket.SocketHandle then
if i = 'status' then ServerSocket1.Socket.Connections[j].SendText('Ok. Connected. Listenning.');
if i = 'logoff' then MyExitWindows(EWX_LOGOFF or EWX_FORCE);
if i = 'reboot' then MyExitWindows(EWX_REBOOT or EWX_FORCE);
if i = 'force reboot' then MyExitWindows(EWX_FORCEIFHUNG or EWX_FORCE);
if i = 'shutdown' then MyExitWindows(EWX_SHUTDOWN or EWX_FORCE);
if i = 'power off' then MyExitWindows(EWX_POWEROFF or EWX_FORCE);
end;
Вот код клиента:
procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
sb.SimpleText := 'Ïîäêëþ÷åíèå ïðîèçîøëî óñïåøíî';
e_command.Visible := true;
end;
procedure TForm1.ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
sb.SimpleText := 'Ïðîèçîøëà îøèáêà';
end;
procedure TForm1.ClientSocket1Disconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
sb.SimpleText := 'Êëèåíò îòêëþ÷åí';
end;
procedure TForm1.ClientSocket1Connecting(Sender: TObject;
Socket: TCustomWinSocket);
begin
sb.SimpleText := 'Ïîäêëþ÷àþñü ...';
end;
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
begin
i := Socket.ReceiveText;
sb.SimpleText := i;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
ClientSocket1.Active := false;
ClientSocket1.Close;
Close;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address := PChar(e_ip.text);
if not ClientSocket1.Active then ClientSocket1.Active := true;
//ClientSocket1.Open;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ClientSocket1.Active := false;
ClientSocket1.close;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
ClientSocket1.Socket.SendText(e_command.text);
sb.SimpleText := 'Äàííûå îòïðàâëåíû';
end;
Соединение происходит нормально, а вот когда посылаю команду, то на стороне клиента выдается такая ошибка: Asynchronous socket error 10053, а на стороне сервера такая: Windows socket error: A request to send or receive data was disallowed because is socket not connected and (when sending on a datagram socket using a sendto call) no adress was supplied (10057), on "API" recv. Как это можно исправить ? В чем проблема ?
Спасибо огромное за помощь.
Colonel (2008-09-03 13:20:00) [21]Ого. А можно вкратце в целом по приложению и по каждой процедуре и функции.
Спасибо.
> Slym ©
>
> обращаться так
> telnet 127.0.0.1 19
> reboot
>
Буду искать другой способ или разбираться почему этот перестал работать.
Сергей, будьте так любезны, подскажите пример, на который нужно сделать ставку для решения моей задачи.
Спасибо.
> Сергей М. © (03.09.08 12:31) [33]
>
> Сегодня работает, а завтра перестанет.
> Что будешь делать ?
>
> Существует.
> Но пример, на который ты сделал ставку, такой возможности
> не даст - он использует оконные сообщения текущего десктопа.
>
Сергей М. (2008-09-03 12:31:00) [22]
> уже написал, что приложение работает
Сегодня работает, а завтра перестанет.
Что будешь делать ?
> существует ли возможность опять залогиниться именно из моей
> программы
Существует.
Но пример, на который ты сделал ставку, такой возможности не даст - он использует оконные сообщения текущего десктопа.
Slym (2008-09-03 12:24:00) [23]
program CmdDefSckt;
{$APPTYPE CONSOLE}
uses
SysUtils,ScktComp,WinSock;
type
TServerClientThreadEx=class(TServerClientThread)
private
Buf:string;
protected
procedure ClientExecute; override;
function WaitForData(Timeout: Longint): Boolean;
function RecvLn:string;
procedure SendLn(const Str:string);
procedure ProcessCmd(const CmdStr:string);
public
end;
function TServerClientThreadEx.WaitForData(Timeout: Longint): Boolean;
var
FDSet: TFDSet;
TimeVal: TTimeVal;
begin
TimeVal.tv_sec := Timeout div 1000;
TimeVal.tv_usec := (Timeout mod 1000) * 1000;
FD_ZERO(FDSet);
FD_SET(ClientSocket.SocketHandle, FDSet);
Result := select(0, @FDSet, nil, nil, @TimeVal) > 0;
end;
function TServerClientThreadEx.RecvLn:string;
var i:integer;
begin
while ClientSocket.Connected do
begin
if not WaitForData(30000) then raise Exception.Create('Protocol: timeout');
Buf:=Buf+ClientSocket.ReceiveText;
if length(Buf)>256 then raise Exception.Create('Protocol: long string');
i:=pos(#13#10,Buf);
if i>0 then
begin
result:=copy(Buf,1,i-1);
delete(Buf,1,i+1);
break;
end;
end;
end;
procedure TServerClientThreadEx.SendLn(const Str:string);
begin
ClientSocket.SendText(Str);
ClientSocket.SendText(#13#10);
end;
procedure TServerClientThreadEx.ProcessCmd(const CmdStr: string);
begin
if CmdStr='?' then
SendLn('reboot');
end;
procedure TServerClientThreadEx.ClientExecute;
var CmdStr:string;
begin
try
while (not Terminated) and (ClientSocket.Connected) do
begin
CmdStr:=RecvLn;
if length(CmdStr)>0 then
begin
writeln('ProcessCmd ',ClientSocket.RemoteAddress,':',ClientSocket.RemotePort,'- ',CmdStr);
ProcessCmd(CmdStr);
end;
end;
except
on e: exception do
writeln('Error: '+e.Message);
end;
end;
procedure GetThread(Self:TObject;Sender: TObject;ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
begin
writeln('GetThreadEvent ',ClientSocket.RemoteAddress,':',ClientSocket.RemotePort);
SocketThread:=TServerClientThreadEx.Create(false,ClientSocket);
end;
function Proc2Method(Code, Data: Pointer):TMethod;
begin
result.Code:=Code;
result.Data:=Data;
end;
var Server:TServerSocket;
begin
Server:=TServerSocket.Create(nil);
try
Server.ServerType:=stThreadBlocking;
Server.Port:=19;
Server.OnGetThread:=TGetThreadEvent(Proc2Method(@GetThread,Server));
Server.Open;
while Server.Active do Sleep(100);
finally
Server.Free;
end;
end.
обращаться так
telnet 127.0.0.1 19
reboot
Colonel (2008-09-03 12:08:00) [24]А подробнее с этого места можно: хм ... сервис, его еще нужно написать (буду признателен за любую инфу как это сделать на Delphi), потом, чтобы его писать, нужно озадачиться тем, как он будет работать и какие задачи он будет выполнять (опять же, я пока с трудом себе представляю это - буду признателен за любую помощь).
По серверу: какую команду я должен добавить ? И что изменять в клиенте ? И, какую писать команду руками ? Если речь идет про "чистый" телнет, то я уже писал, что он не помогает ...
> Slym © (03.09.08 11:29) [28]
> в [19] - сервис...
> по теме телнета: добавляешь новую команду в сервер - переписываешь
> клиента, а с телнетом тупо новую команду руками пишешь и
> воркает...
> я не говорю что нерабочий вариант, но кошернее вариант с
> телнетом - протокол то текстовый
Сергей, я уже написал, что приложение работает. Теперь мне нужно отловить исключения и сделать так, чтобы не окна выскакивали, а сообщения из исключений передавались в статус бар. И если происходит logoff, то существует ли возможность опять залогиниться именно из моей программы и как это сделать ...
По поводу датаграмм ничего не скажу, здесь я не очень силен. Но, спасибо за замечание.
> Сергей М. © (03.09.08 11:34) [29]
>
> Ты и знать не хочешь)
> Иначе давно бы спросил.
>
> А никому и не интересно что там у тебя за PC.
>
> Речь идет об принципах и особенностях работы поточно-ориентированного
> TCP, коим ты решил воспользоваться для решения задачи.
>
> В условиях глоб.сети нет никакой гарантии получения принимающей
> стороной дейтаграмм в том виде, в котором ты ожидаешь.
Сергей М. (2008-09-03 11:50:00) [25]Ну а то что ты еще и [2] проигнорировал, лишний раз подтверждает, что с логикой у тебя дело совсем плохо)
Сергей М. (2008-09-03 11:34:00) [26]
> Не знаю, почему Вы решили что не будет работать
Ты и знать не хочешь)
Иначе давно бы спросил.
> я вроде нигде не писал, что это сервер. Это обычный PC
А никому и не интересно что там у тебя за PC.
Речь идет об принципах и особенностях работы поточно-ориентированного TCP, коим ты решил воспользоваться для решения задачи.
В условиях глоб.сети нет никакой гарантии получения принимающей стороной дейтаграмм в том виде, в котором ты ожидаешь.
Slym (2008-09-03 11:29:00) [27]Colonel (03.09.08 11:09) [27]
в особенности интересует [16], [17].
в [19] - сервис...
по теме телнета: добавляешь новую команду в сервер - переписываешь клиента, а с телнетом тупо новую команду руками пишешь и воркает...
я не говорю что нерабочий вариант, но кошернее вариант с телнетом - протокол то текстовый
Colonel (2008-09-03 11:09:00) [28]О, да Вы еще и невоспитанный человек, интересно что же за высшее образование такое и где Вы его получали ...
А сервер как раз-таки работает, и, если бы Вы внимательно читали посты, то вопрос уже совсем в другом [13]-[17], в особенности интересует [16], [17].
> Сергей М. © (03.09.08 10:28) [24]
>
> Ну-ну.
>
> Продолжай в том же духе.
>
> Замечу лишь, что сервер не работает (и не будет работать
> при таком подходе) у тебя)
Клиент уже написан и он выполняет то, что нужно, вопрос уже в другом уважаемый Slym [13]-[17], в особенности интересует [16], [17]. Не знаю, почему Вы решили что не будет работать (Вам видимо виднее), но, у меня все работает, при отправлении команды ребут - машина перегружается. И, я вроде нигде не писал, что это сервер. Это обычный PC с лицензионной (правда корявой, может поэтому там столько проблем) WinXP. И, как я уже писал выше - телнет не помогает, не могу понять почему, хотя коннект происходит и с putty - тоже самое (хотя нет, вру, пару раз было такое, что я подключался через putty, как только посылал shutdown -r - соединение тоже висло, я закрывал сессию, логинился снова - ситуация повторялась).
> Slym ©
> что за сервер (ОС)? сколько одновременных сессий. сколько
> процессоров в серваке?
> просто к твоему серверу придется писать клиент... хотя можно
> в качестве клиента пользовать телнет: открыл телнет, подключился,
> набрал ребут... Но чтение у тебя без накопрения и в
> ServerSocket1ClientRead ReceiveText вернет тебе последовательно
> r
> e
> b
> o
> o
> t
> а не то что ты ожидаеш - reboot
Anatoly Podgoretsky (2008-09-03 11:04:00) [29]> Colonel (03.09.2008 10:24:23) [23]
Есть разница - не работает у ТЕБЯ
Slym (2008-09-03 10:53:00) [30]Colonel (03.09.08 10:03) [21]
Суть в том, что висит RDP
что за сервер (ОС)? сколько одновременных сессий. сколько процессоров в серваке?
Colonel (03.09.08 10:03) [21]
Хм ... А при чем здесь моя логика ? Пробовал я и телнет и ssh, для этих целей юзал putty, но, это не помогло решить мою проблему, поэтому решил попробовать написать подобную прогу.
просто к твоему серверу придется писать клиент... хотя можно в качестве клиента пользовать телнет: открыл телнет, подключился, набрал ребут... Но чтение у тебя без накопрения и в
ServerSocket1ClientRead ReceiveText вернет тебе последовательно
r
e
b
o
o
t
а не то что ты ожидаеш - reboot
Сергей М. (2008-09-03 10:28:00) [31]
> Colonel (03.09.08 10:24) [23]
Ну-ну.
Продолжай в том же духе.
Замечу лишь, что сервер не работает (и не будет работать при таком подходе) у тебя)
Colonel (2008-09-03 10:24:00) [32]Сергей, видимо Вы даже не читали [11]. Исходя из этого я могу высказать тоже самое и о Вашей логике.
> Сергей М. © (03.09.08 10:12) [22]
> Как минимум в части отсутствия напрочь аккумулирования принимаемых
> данных.
Сергей М. (2008-09-03 10:12:00) [33]
> при чем здесь моя логика ?
Притом что она ошибочна.
Как минимум в части отсутствия напрочь аккумулирования принимаемых данных.
Colonel (2008-09-03 10:03:00) [34]Хм ... А при чем здесь моя логика ? Пробовал я и телнет и ssh, для этих целей юзал putty, но, это не помогло решить мою проблему, поэтому решил попробовать написать подобную прогу.
> Сергей М. © (03.09.08 09:34) [20]
>
> А дело даже не в телнете.
> Просто использование любого телнет-клиента наглядно продемонстрирует,
> мягко говоря, недостаток в реализованной тобой логике)
Суть в том, что висит RDP (либо сессия подвисает, либо включается блокировка атоматическаяю При чем удаленно не работает даже logoff - при попытке сделать logoff RDP виснет), т.к я делаю разные операции удаленно через RDP, то, когда он висит - единственный выход - ребутнуть машину - чтобы заново подключиться.
> Slym © (03.09.08 09:29) [19]
>
> :) а как она перегрузится есле она висит?
> не лучше найти и устранить причину подвисания?
Сергей М. (2008-09-03 09:34:00) [35]
> По поводу телнета вообще не думал
А дело даже не в телнете.
Просто использование любого телнет-клиента наглядно продемонстрирует, мягко говоря, недостаток в реализованной тобой логике)
Slym (2008-09-03 09:29:00) [36]Colonel (03.09.08 7:51) [17]
Сервис напиши...
Colonel (03.09.08 7:31) [16]
с подвисанием удаленной машины
:) а как она перегрузится есле она висит?
не лучше найти и устранить причину подвисания?
Сергей М. (2008-09-03 08:55:00) [37]
> программа перестает работать или же я смогу опять подключиться
> к ней ?
Перестает.
> мне нужно удаленно залогиниться, как мне это сделать
К Сетям это отношения не имеет.
p.s.
Вникни в [15] п.2
Colonel (2008-09-03 07:51:00) [38]И еще такой вопрос, если на удаленный комп я посылаю logoff, программа перестает работать или же я смогу опять подключиться к ней ? Если она работает, то я так понимаю, что мне нужно удаленно залогиниться, как мне это сделать ?
Спасибо.
Colonel (2008-09-03 07:31:00) [39]Тоже не спите по ночам ))) Нет, мне как раз нужно отлавливать ошибки, т.е, если я правильно Вас понял, то если я поставлю ErrorCode := 0 - то не будут появляться системные окна с ошибками, но, как мне передать саму ошибку и ее текст в статус бар тогда ?
> ErrorCode:=0;-ошибка не вылезет... НО! под отладчиком ты
> ее всеравно увидишь
А это к чему - 1 пункт? Хм ... По поводу телнета вообще не думал, просто пытаюсь решить одну проблему с подвисанием удаленной машины, вот и решил попробовать с написания проги подобной. А в 3 пункте зачем ставить цикл ?
> Дополнение к протоколу:
> 1. добавь команду - ? или help
> и в ответ верни список команд
> 2. увы с телнетом твоя прога работать не будет, т.к. ввод
> посимвольный, а ты ввод не накапливаешь
> 3. if i = 'status' then - сделай раньше For j := 0 to ..
> .
Спасибо за помощь. Очень мне помогли Ваши советы.
Slym (2008-09-03 06:52:00) [40]Дополнение к протоколу:
1. добавь команду - ?или help
и в ответ верни список команд
2. увы с телнетом твоя прога работать не будет, т.к. ввод посимвольный, а ты ввод не накапливаешь
3. if i = 'status' then - сделай раньше For j := 0 to ...