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

Вниз

stThreadBlocking   Найти похожие ветки 

 
Timon ©   (2002-08-28 18:24) [0]

Помогите, пожалуйста. Мне СРОЧНО нужен ответ на следующие вопросы

- Происходит ли при этом режиме сервера событие OnClientConnect
- В каких случаях происходит событие OnGetThread, OnThreadStart, OnThreadEnd.
- И если можно, пример сервера такого типа

Пожалуюста не отправляйте меня в справку Delphi, так как ни ее, ни дистрибутива у меня нет.


 
Digitman ©   (2002-08-29 08:21) [1]

А в исх.текст в scktcomp.pas тебя можно отправить ?)



procedure TServerWinSocket.Accept(Socket: TSocket);
var
ClientSocket: TServerClientWinSocket;
ClientWinSocket: TSocket;
Addr: TSockAddrIn;
Len: Integer;
OldOpenType, NewOpenType: Integer;
begin
Len := SizeOf(OldOpenType);
if getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType),
Len) = 0 then
try
if FServerType = stThreadBlocking then
begin
NewOpenType := SO_SYNCHRONOUS_NONALERT;
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@NewOpenType), Len);
end;
Len := SizeOf(Addr);
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
if ClientWinSocket <> INVALID_SOCKET then
begin
ClientSocket := GetClientSocket(ClientWinSocket); // вызов события OnGetSocket в теле GetClientSocket()
if Assigned(FOnSocketEvent) then
FOnSocketEvent(Self, ClientSocket, seAccept); // вызов события OnAccept()
if FServerType = stThreadBlocking then
begin
ClientSocket.ASyncStyles := [];
GetServerThread(ClientSocket); // вызов события OnGetThread в теле GetServerThread()
end;
end;
finally
Len := SizeOf(OldOpenType);
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType), Len);
end;
end;



procedure TServerClientThread.Execute;
begin
FServerSocket.ThreadStart(Self); // вызов события OnThreadStart
try
try
while True do
begin
if StartConnect then ClientExecute;
if EndConnect then Break;
end;
except
HandleException;
KeepInCache := False;
end;
finally
FServerSocket.ThreadEnd(Self); // вызов события OnThreadEnd
end;
end;


 
Timon ©   (2002-08-29 10:47) [2]


Спасибо большое Цифровойчеловек. Звиняюсь за свою тупость, в исходники посмотреть не догадался.


 
Timon ©   (2002-08-29 10:54) [3]


А еще, это нормально, что при подключении IExplorer-a к серверу с типом stThreadBlocking и сервер и IExplorer начинают жутко притормазивать?


 
Digitman ©   (2002-08-29 11:07) [4]

>Timon

С чего бы нормально ? Видимо, логика TServerClientThread.ClientExecute неверно реализована


 
Timon ©   (2002-08-29 11:15) [5]


> Digitman

Видимо, логика TServerClientThread.ClientExecute неверно реализована

А я могу что-нть сделать с этим?


 
Timon ©   (2002-08-29 11:19) [6]


А все, понял, звиняюсь еще раз за свою тупость. Этот метод я должен пропсать. Тьфу, вот что значит отсутствие справки :))
Спасибо тебе Digitman большое, тоже всегда буду рад помочь.


 
Digitman ©   (2002-08-29 11:35) [7]

>Timon

Совершенно верно.
TServerClientThread.ClientExecute - виртуальный метод.
В нем реализована примитивная транспортная логика, подходящая далеко не для всех задач.

В событии OnGetGhread() ты волен указать собственного объекта -наследника класса TServerClientThread, переопределенный ClientExecute-метод которого реализует требуемую тебе логику (возврат результирующего nil вместо ссылки на собственного наследника диспетчером события OnGetThread интерпретируется объектом TServerWinSocket как отказ от индивидуальной логики, и в результате по-умолчанию будет создан экземпляр базового класса TServerClientThread с базовой логикой). Коль скоро ты отказываешься от дифолта, ответственность за корректность транспортной (и иной) логики в методе ClientExecute своего наследника возлагается полностью на тебя.

P.S. Не вздумай в своей реализации ClientExecute() (если он таки своими силами реализует транспорт) вызывать
inherited ClientExecute - получишь полный бардак с транспортом.


 
Timon ©   (2002-08-29 13:15) [8]


А когда соединение будет разорвано мой "транспортировщик" будет уничтожен автоматически? У меня при выходе из процедуры ClientExecute ошибка обр к памяти происходит. Выход делается если ClientConnection.Connected = false или Terminated = true.


 
Digitman ©   (2002-08-29 13:46) [9]

Будет уничтожен экземпляр-наследник TServerClientThread или нет - это зависит от параметров кэша код.потоков объекта класса TServerSocket.


Опять же - смотри исх.текст в части всего, что связано с этими вот свойствами : ActiveThreads, ThreadCacheSize и KeepInCache

Приводи декларацию и полный код своего наследника TServerClientThread (а так же текст обработчиков OnGetThread, OnGetSocket) - разберемся, что у тебя там за беда.


 
Timon ©   (2002-08-29 15:25) [10]


Вот сл код


Procedure tpServerThread.ClientExecute;
begin
sStream:=tWinSocketStream.Create(ClientSocket,300);
GetMem(BufferFS,10000);
While (not Terminated) and (ClientSocket.Connected) do
begin
if BuffFSLen>0 then
begin
if Assigned(ClientReceive) then
BuffFSLen:=ClientReceive (ClientSocket.RemoteAddress,BufferFS,BuffFSLen);
if BuffFSLen>0 then sStream.Write(BufferFS[0],BuffFsLen) else
ClientSocket.Close;
BuffFSLen:=0;
end;
try
if sStream.WaitForData(10) then
begin
try
if assigned(sStream) then
if ClientSocket.Connected then BuffFSLen:=sStream.Read(BufferFS[0],10000)
else break else BuffFSLen:=0;
if (BuffFSLen>0) and Assigned(SendToClient) then
if Assigned(ClientSend) then if ClientSend(ClientSocket.RemoteAddress,BufferFS,BuffFSLen) then
SendToClient(BufferFS,BuffFSLen) else ClientSocket.Close;
BuffFSLen:=0;
except
break;
end;
end;
except
break;
end;
end;
SStream.Free;
FreeMem(BufferFS,10000);
if Assigned(CloseConnection) then CloseConnection;
end;


Где BufferFS:pChar - буффер обмена. Я простенький прокси пишу.


 
Timon ©   (2002-08-29 15:26) [11]


Да, еще есть беда. tClientSocket в режиме ctBlocking не вызывает событие OnDisconnect. А как тогда определять, что соединение разорвано?


 
Digitman ©   (2002-08-29 16:19) [12]

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


ладно.
1.Зачем используешь TWinSocketStream ? Чем это обосновано ?
2. Зачем закрываешь соединение , если буфер приема/передачи пуст ?



 
Timon ©   (2002-08-29 17:47) [13]


> Digitman

Прошу прощения за кривой текст. Так писать быстрее, а читать наоборот :(
Зачем используешь TWinSocketStream ? Чем это обосновано ?


Ну надо же как-то получать и отправлять данные в сообщение. Есть другой способ?

Зачем закрываешь соединение , если буфер приема/передачи пуст

Я соединение закрываю не когда буфер пуст, а когда ему запрещено пересылать данные. Это узнает ф-я ClientReceive(Address:String; Buffer:pChar; bLen:Longint):Longint;


 
Digitman ©   (2002-08-29 18:18) [14]


> Ну надо же как-то получать и отправлять данные в сообщение.
> Есть другой способ?


Конечно, есть) ClientSocket.SendBuf()/ReceiveBuf() - гораздо более гибкие и чувствительные к отказам транспорта методы

> Я соединение закрываю не когда буфер пуст, а когда ему запрещено
> пересылать данные. Это узнает ф-я ClientReceive(Address:String;
> Buffer:pChar; bLen:Longint):Longint;


странно. сначала ты установил соединение с клиентом, а потом вдруг ни с того ни с сего рвешь его. Зачем тогда устанавливать соединение, если оно нежелательно ?


 
Timon ©   (2002-08-29 18:37) [15]

> Digitman

А объясни пожалуйста, почему соединение с сервером обрывается, а св-во ClientSocket.Connected так и остается True, из-за чего у меня выход из ClientExecute не происходит.


 
Digitman ©   (2002-08-29 18:52) [16]

А в исх.текст - снова лень глянуть ?

Гнездо у тебя - блокирующее. Практически любые отказы транспорта будут ловиться в try..except. В блоке except ты обязан сам установить св-во Connected = False, если отказ некоего блокирующего вызова send/recv связан с разрывом вирт.перли соединения по тем или иным причинам (причина выясняется элементарно - on E:ESocketConnectionError do .. ). И цикл будет прерван при очередной проверке while Connected

Еще раз - гнездо НЕ-БЛО-КИ-РУ-Ю-ЩЕ-Е ! Никто за тебя св-вом Connected в этом режиме управлять не будет - ты сам должен это делать.


 
Digitman ©   (2002-08-29 18:56) [17]

Во) ... заболтался уже)))) ... извини

Блокирующее гнездо ты используешь. Вернее, даже не гнездо, а ф-ции WinsockAPI, управляющие гнездовым транспортом, являются блокирующими.


 
Timon ©   (2002-08-29 19:25) [18]


В блоке except ты обязан сам установить св-во Connected = False

1. Так он ReadOnly
2. У меня EXCEPT не происходит!

Извини меня пожалуйста Digitman, достал я тебя уже наверное. Если можешь, кинь мне лучше на мыло работающий пример такой процедуры. Хотя можно и сюда кинуть :))


 
Digitman ©   (2002-08-30 08:59) [19]


> Так он ReadOnly


Ну ты и лентяй !)
Снова отсылаю тебя в исх.текст.

Я что, помнить должен, ReadOnly оно или не ReadOnly ? Да мало ли методов/св-в, позволяющих закрыть соединение ? Ну возьми да Close() вызови, какая разница ! Неужели так трудно посмотреть, что Connected всего лишь читает приватное поле FConnected, а потом поискать методы, изменяющие состояние этого поля ?


> 2. У меня EXCEPT не происходит!


Так ты нигде и не обращаешься непосредственно к методам SendBuf()/ReceiveBuf() !


> кинь ... работающий пример


Опять же - отсылаю тебя к исходникам, в демо-проект Borland Socket Server (scktsrvr.dpr). Он обязательно должен быть в штатной поставке Делфи



 
Digitman ©   (2002-08-30 09:04) [20]


function TCustomWinSocket.SendBuf(var Buf; Count: Integer): Integer;
var
ErrorCode: Integer;
begin
Lock;
try
Result := 0;
if not FConnected then Exit;
Result := send(FSocket, Buf, Count, 0); //попытка записи
if Result = SOCKET_ERROR then //если отказ транспорта
begin
ErrorCode := WSAGetLastError;
if (ErrorCode <> WSAEWOULDBLOCK) then // если - блок.режим
begin
Error(Self, eeSend, ErrorCode); //событие OnError
Disconnect(FSocket); // закрыть транспорт
if ErrorCode <> 0 then // если в событии OnError() ошибка не сброшена в нуль
// возбудить исключение !!!!
raise ESocketError.CreateResFmt(@sWindowsSocketError,
[SysErrorMessage(ErrorCode), ErrorCode, "send"]);

end;
end;
finally
Unlock;
end;
end;



 
Timon ©   (2002-08-30 15:17) [21]


Извини меня Digitman, за лень природную и т.д. Я сегодня ночью не поленился и разобрался таки! Работает :) Все завершается, все посылается :) Вощем rulezzz! Как раз успел.



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

Текущий архив: 2002.10.31;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.01 c
3-101138
sdram
2002-10-10 11:56
2002.10.31
Можно ли в одном запросе почистить несвязанные записи


4-101571
igornov
2002-09-11 17:50
2002.10.31
Как получить % загрузки процесора конкретным приложением?


7-101532
Автответчик
2002-08-21 16:28
2002.10.31
Как программно позвонить через модем и сказать стандартную фразу?


1-101184
Alderman
2002-10-21 11:26
2002.10.31
Как найти утечки памяти?


3-101124
ПИТОН
2002-10-09 14:45
2002.10.31
TStringList в таблицу