Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

stThreadBlocking


Страницы:   1 2

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]


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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо