![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
stThreadBlocking
Timon © (2002-08-28 18:24:00)Помогите, пожалуйста. Мне СРОЧНО нужен ответ на следующие вопросы
- Происходит ли при этом режиме сервера событие OnClientConnect
- В каких случаях происходит событие OnGetThread, OnThreadStart, OnThreadEnd.
- И если можно, пример сервера такого типа
Пожалуюста не отправляйте меня в справку Delphi, так как ни ее, ни дистрибутива у меня нет.
Timon (2002-08-30 15:17:00) [1]
Извини меня Digitman, за лень природную и т.д. Я сегодня ночью не поленился и разобрался таки! Работает :) Все завершается, все посылается :) Вощем rulezzz! Как раз успел.
Digitman (2002-08-30 09:04:00) [2]
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;
Digitman (2002-08-30 08:59:00) [3]
> Так он ReadOnly
Ну ты и лентяй !)
Снова отсылаю тебя в исх.текст.
Я что, помнить должен, ReadOnly оно или не ReadOnly ? Да мало ли методов/св-в, позволяющих закрыть соединение ? Ну возьми да Close() вызови, какая разница ! Неужели так трудно посмотреть, что Connected всего лишь читает приватное поле FConnected, а потом поискать методы, изменяющие состояние этого поля ?
> 2. У меня EXCEPT не происходит!
Так ты нигде и не обращаешься непосредственно к методам SendBuf()/ReceiveBuf() !
> кинь ... работающий пример
Опять же - отсылаю тебя к исходникам, в демо-проект Borland Socket Server (scktsrvr.dpr). Он обязательно должен быть в штатной поставке Делфи
Timon (2002-08-29 19:25:00) [4]
В блоке except ты обязан сам установить св-во Connected = False
1. Так он ReadOnly
2. У меня EXCEPT не происходит!
Извини меня пожалуйста Digitman, достал я тебя уже наверное. Если можешь, кинь мне лучше на мыло работающий пример такой процедуры. Хотя можно и сюда кинуть :))
Digitman (2002-08-29 18:56:00) [5]Во) ... заболтался уже)))) ... извини
Блокирующеегнездо ты используешь. Вернее, даже не гнездо, а ф-ции WinsockAPI, управляющие гнездовым транспортом, являются блокирующими.
Digitman (2002-08-29 18:52:00) [6]А в исх.текст - снова лень глянуть ?
Гнездо у тебя - блокирующее. Практически любые отказы транспорта будут ловиться в try..except. В блоке except ты обязан сам установить св-во Connected = False, если отказ некоего блокирующего вызова send/recv связан с разрывом вирт.перли соединения по тем или иным причинам (причина выясняется элементарно - on E:ESocketConnectionError do .. ). И цикл будет прерван при очередной проверке while Connected
Еще раз - гнездо НЕ-БЛО-КИ-РУ-Ю-ЩЕ-Е ! Никто за тебя св-вом Connected в этом режиме управлять не будет - ты сам должен это делать.
Timon (2002-08-29 18:37:00) [7]> Digitman
А объясни пожалуйста, почему соединение с сервером обрывается, а св-во ClientSocket.Connected так и остается True, из-за чего у меня выход из ClientExecute не происходит.
Digitman (2002-08-29 18:18:00) [8]
> Ну надо же как-то получать и отправлять данные в сообщение.
> Есть другой способ?
Конечно, есть) ClientSocket.SendBuf()/ReceiveBuf() - гораздо более гибкие и чувствительные к отказам транспорта методы
> Я соединение закрываю не когда буфер пуст, а когда ему запрещено
> пересылать данные. Это узнает ф-я ClientReceive(Address:String;
> Buffer:pChar; bLen:Longint):Longint;
странно. сначала ты установил соединение с клиентом, а потом вдруг ни с того ни с сего рвешь его. Зачем тогда устанавливать соединение, если оно нежелательно ?
Timon (2002-08-29 17:47:00) [9]
> Digitman
Прошу прощения за кривой текст. Так писать быстрее, а читать наоборот :(
Зачем используешь TWinSocketStream ? Чем это обосновано ?
Ну надо же как-то получать и отправлять данные в сообщение. Есть другой способ?
Зачем закрываешь соединение , если буфер приема/передачи пуст
Я соединение закрываю не когда буфер пуст, а когда ему запрещено пересылать данные. Это узнает ф-я ClientReceive(Address:String; Buffer:pChar; bLen:Longint):Longint;
Digitman (2002-08-29 16:19:00) [10]ну и понаворочал ты !
хоть бы отступы расставил как положено ... читать невозможно
да прокомментировал бы, где что делаешь, раз не сподобился привести то, что я просил, целиком
ладно.
1.Зачем используешь TWinSocketStream ? Чем это обосновано ?
2. Зачем закрываешь соединение , если буфер приема/передачи пуст ?
Timon (2002-08-29 15:26:00) [11]
Да, еще есть беда. tClientSocket в режиме ctBlocking не вызывает событие OnDisconnect. А как тогда определять, что соединение разорвано?
Timon (2002-08-29 15:25:00) [12]
Вот сл код
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 - буффер обмена. Я простенький прокси пишу.
Digitman (2002-08-29 13:46:00) [13]Будет уничтожен экземпляр-наследник TServerClientThread или нет - это зависит от параметров кэша код.потоков объекта класса TServerSocket.
Опять же - смотри исх.текст в части всего, что связано с этими вот свойствами : ActiveThreads, ThreadCacheSize и KeepInCache
Приводи декларацию и полный код своего наследника TServerClientThread (а так же текст обработчиков OnGetThread, OnGetSocket) - разберемся, что у тебя там за беда.
Timon (2002-08-29 13:15:00) [14]
А когда соединение будет разорвано мой "транспортировщик" будет уничтожен автоматически? У меня при выходе из процедуры ClientExecute ошибка обр к памяти происходит. Выход делается если ClientConnection.Connected = false или Terminated = true.
Digitman (2002-08-29 11:35:00) [15]>Timon
Совершенно верно.
TServerClientThread.ClientExecute - виртуальный метод.
В нем реализована примитивная транспортная логика, подходящая далеко не для всех задач.
В событии OnGetGhread() ты волен указать собственного объекта -наследника класса TServerClientThread, переопределенный ClientExecute-метод которого реализует требуемую тебе логику (возврат результирующего nil вместо ссылки на собственного наследника диспетчером события OnGetThread интерпретируется объектом TServerWinSocket как отказ от индивидуальной логики, и в результате по-умолчанию будет создан экземпляр базового класса TServerClientThread с базовой логикой). Коль скоро ты отказываешься от дифолта, ответственность за корректность транспортной (и иной) логики в методе ClientExecute своего наследника возлагается полностью на тебя.
P.S. Не вздумай в своей реализации ClientExecute() (если он таки своими силами реализует транспорт) вызывать
inherited ClientExecute - получишь полный бардак с транспортом.
Timon (2002-08-29 11:19:00) [16]
А все, понял, звиняюсь еще раз за свою тупость. Этот метод я должен пропсать. Тьфу, вот что значит отсутствие справки :))
Спасибо тебе Digitman большое, тоже всегда буду рад помочь.
Timon (2002-08-29 11:15:00) [17]
> Digitman
Видимо, логика TServerClientThread.ClientExecute неверно реализована
А я могу что-нть сделать с этим?
Digitman (2002-08-29 11:07:00) [18]>Timon
С чего бы нормально ? Видимо, логика TServerClientThread.ClientExecute неверно реализована
Timon (2002-08-29 10:54:00) [19]
А еще, это нормально, что при подключении IExplorer-a к серверу с типом stThreadBlocking и сервер и IExplorer начинают жутко притормазивать?
Timon (2002-08-29 10:47:00) [20]
Спасибо большое Цифровойчеловек. Звиняюсь за свою тупость, в исходники посмотреть не догадался.