![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TSocketServer без формы [D7, Win2k]
Obsidee © (2007-10-02 13:35:00)Когда создаю TSocketServer на форме, кидая компонент, создаю событие OnRead, всё проходит легко и просто.
Но когда создаю в RTTI, то никакие события не вызываются?
что я делаю не так?
простой пример:
unit SS;
interface
uses
Classes, ScktComp, SysUtils;
type TServerThread = class (TThread)
private
SSocket :TServerSocket;
procedure OnRead (Sender: TObject; Socket: TCustomWinSocket);
protected
procedure Execute; override;
public
Constructor Create;
end;
implementation
constructor TServerThread.Create;
begin
inherited Create (false);
SSocket:=TServerSocket.Create(nil);
SSocket.Port:=80;
SSocket.OnClientRead := OnRead;
SSocket.Active:=true;
end;
procedure TServerThread.Execute;
begin
inherited;
self.Priority:=tpLower;
while not self.Terminated do sleep(1);
end;
procedure TServerThread.OnRead(Sender: TObject; Socket: TCustomWinSocket);
var
s: string;
begin
s:= socket.ReceiveText;
Writeln(s);
end;
VaRela (2007-10-19 12:45:00) [1]Доброе время суток всем, борюсь со следующей проблемой:
TServerSocket работает в блокирующем режиме, создал своего наследника для потока TServerClientThread. В ClientExecute вертится следующий цикл (прошу прощения что BCB):
while (!Terminated && ClientSocket->Connected)
{
.....
}
Цикл работает отлично, но при отключении клиента НЕ ЗАВЕРШАЕТСЯ!, никак не соображу почему.
Как можно узнать что клиент отключился?
P.S. Клиент не мой, переписать не смогу, протокола не знаю. :-)
Evgeny V (2007-10-04 10:24:00) [2]
> DiamondShark © (03.10.07 18:56) [27]
Хотя извиняюсь, в
> Evgeny V © (04.10.07 07:06) [29]
я наврал. С оверлаппед сокетами все сложнее. Просто подзабыл что EventSelect и overlapped сокеты это разное:-)
Evgeny V (2007-10-04 07:06:00) [3]
> DiamondShark © (03.10.07 18:56) [27]
> Ну, теперь уже не всегда. Есть ведь overlapped IO, что намного
> удобнее.
В Windows всегда.
MSDN ioctlsocket
> The WSAAsyncSelect and WSAEventSelect functions automatically
> set a socket to nonblocking mode
Оно и понятно, что сокет должен быть неблокирующим. Иначе как бы мы могли вызвав recv, потом в этом же потоке подождать события функцией WSAWaitForMultipleEvents, ибо висели бы на вызове recv, если сокет блокирующий.
Slym (2007-10-04 04:51:00) [4]DiamondShark © (03.10.07 17:25) [24]
Я для себя сделал BlockScktComp - взял стандартный ScktComp и вырезал от туда всю асинхронику
DiamondShark (2007-10-03 18:56:00) [5]
> DVM © (03.10.07 17:34) [25] [26]
Это всё понятно.
Только вот в компонентах под "неблокирующими" подразумеваются именно асинхронные сокеты на сообщениях.
> Просто так сложилось, что в Windows асинхронные сокеты -
> это всегда неблокирующие сокеты
Ну, теперь уже не всегда. Есть ведь overlapped IO, что намного удобнее.
DVM (2007-10-03 17:40:00) [6]Просто так сложилось, что в Windows асинхронные сокеты - это всегда неблокирующие сокеты, но неблокирующие сокеты - это не всегда асинхронные.
DVM (2007-10-03 17:34:00) [7]
> Потому что, как тут верно, но не полно вспомнили, "наследие
> царского режима".
Наследие это асинхронные сокеты на сообщениях, а не неблокирующие. А говорите, что не путаете. Неблокирующие сокеты ничем не хуже и не лучше блокирующих, были и есть и используются и в Unix и в Windows. А вот асинхронные сокеты на сообщениях - это изобретение MS для ранних версий Win (3.11), так как в них с многопоточностью было все не очень гладко.
DiamondShark (2007-10-03 17:25:00) [8]
> DVM © (03.10.07 15:38) [21]
> Почему зло?
Потому что, как тут верно, но не полно вспомнили, "наследие царского режима".
> DVM © (03.10.07 15:39) [22]
> И не надо путать неблокирущие и асинхронные сокеты. Это
> не одно и то же.
Не напомнишь, кто, где и когда утверждал, что это одно и то же?
> Сергей М. © (03.10.07 15:49) [23]
> "Вы не любите кошек ? Да вы просто не умеете их готовить
> !" (С)
Я так понял, это был Аргумент?
> А аргументы, конечно же, - "наследие царского режима")
Не затруднит напомнить полную версию текста, откуда ты отквоченное выдрал?
Как только сподобишься, получишь аргумент на "сорняк".
А "мутант" -- так это борландовское исполнение обёртки, к которой две основные претензии:
1. Мутное обращение с сущностями.
Не вводится никакой новой абстракции. Нафига объектная обёртка? Ладно, допустим, для батонокидательства. Но экономия трудоёмкости мизерная, объём рукописного кода соизмерим с прямым использованием WS API.
Смешиваются сущности. В блокирующем и неблокирующем режимах используются разные наборы методов (либо общие методы, но изобилующие if Block then ... else ...), это наводит на мысль о разных ветвях наследования.
2. Сокрытая сложность и неочевидные требования к окружению.
В неблокирующем режиме компоненты используют механизм оконных сообщений и, как следствие, требуют message pump. Эта зависимость от окружения не только не очевидна из публичного интерфейса классов, но даже не отражена в документации. Обнаружить эту особенность можно либо стукнувшись лбом (как в субже), либо зная детали реализации (тогда вопрос: нафиг нужны такие weak-incapsulated компоненты?).
Сергей М. (2007-10-03 15:49:00) [9]
> Сокетные компоненты (по кр.м., в исполнении борманда) --
> ещё большее зло
"Вы не любите кошек ? Да вы просто не умеете их готовить !" (С)
> это сорняк-мутант
Ну да.
А аргументы, конечно же, - "наследие царского режима")
DVM (2007-10-03 15:39:00) [10]И не надо путать неблокирущие и асинхронные сокеты. Это не одно и то же.
DVM (2007-10-03 15:38:00) [11]
> > неблокирующий сокет - зло
>
> Зло, бес с порно.
Почему зло?
DiamondShark (2007-10-03 15:20:00) [12]
> неблокирующий сокет - зло
Зло, бес с порно.
Сокетные компоненты (по кр.м., в исполнении борманда) -- ещё большее зло.
> Притчу про "всякий овощ .." помнишь ?)
Это не овощ, это сорняк-мутант.
Сергей М. (2007-10-03 08:20:00) [13]
> Slym © (03.10.07 05:54) [18]
>
> неблокирующий сокет - зло
Притчу про "всякий овощ .." помнишь ?)
Slym (2007-10-03 05:54:00) [14]неблокирующий сокет - зло
program CharGen;
{$APPTYPE CONSOLE}
uses SysUtils,ScktComp,WinSock;
type
TServerClientThreadEx=class(TServerClientThread)
protected
procedure ClientExecute; override;
end;
procedure TServerClientThreadEx.ClientExecute;
var i:integer;
begin
Randomize;
while (not Terminated) and ClientSocket.Connected do
begin
try
i:=Random(MaxInt);
ClientSocket.SendBuf(i,SizeOf(i));
except
Terminate;
HandleException;
end;
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:=3128;
Server.OnGetThread:=TGetThreadEvent(Proc2Method(@GetThread,Server));
Server.Open;
while Server.Active do Sleep(100);
finally
Server.Free;
end;
end.
Obsidee (2007-10-02 17:55:00) [15]
procedure TServer.Close;
begin
PostThreadMessage(ThreadID,WM_QUIT,0,0);
end;
PostQuitMessage(0);не работает, хотя должен вызывать WM_QUIT
в примере FearG0 © [7] вызывается WM_CLOSE, но, насколько я знаю, WM_QUIT - единственный кто вызывает у методаGetMessage =false
Сергей М. (2007-10-02 17:11:00) [16]
> по поводу terminate
> в OnTerminate server.close;
OnTerminate - это уже следствие, а не причина.
А причина - это корректное завершение выполнения метода Execute.
А Execute у тебя не завершится по кр.мере до момента обнаружения взведенного флага Terminated.
А флаг Terminated ты не можешь проанализировать, пока ты "висишь" на блокирующем вызове GetMessage
Фершейн, надеюсь ?)
Obsidee (2007-10-02 17:02:00) [17]
> > procedure TServerThread.Execute;
> > begin
> > inherited;
>
>
> Это зачем ?
остался от ctrl+shift+c
для абстрактного метода бессмысленно вызывать
по поводуterminate
в OnTerminateserver.close;
это просто быстросделанныйunit, чтобы показать что я делаю сTServerSocket
Сергей М. (2007-10-02 16:34:00) [18]
> procedure TServerThread.Execute;
> begin
> inherited;
Этозачем ?
Сергей М. (2007-10-02 16:33:00) [19]
> TranslateMessage(Msg);
Это лишнее.
> всё наконецто заработало
А где реакция на команду терминирования потока ?
Obsidee (2007-10-02 16:29:00) [20]вставив в Exetune
while GetMessage(msg, 0,0,0)
do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
всё наконецто заработало...