Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2002.10.31;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.01 c
1-101184
Alderman
2002-10-21 11:26
2002.10.31
Как найти утечки памяти?


6-101419
Enton
2002-08-31 23:07
2002.10.31
Как проверить существование файла в интернет


3-101164
BCPP_Builder_Dev
2002-10-11 13:02
2002.10.31
Коллеги подскажите! Вопрос пор QuickReports.


1-101369
Prior
2002-10-20 13:17
2002.10.31
Как узнать сколько памяти требует программа?


1-101362
brestmarket
2002-10-20 11:52
2002.10.31
Как лучше определить что ссылка в WebBrowser - путь к каталогу ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский