Форум: "Сети";
Текущий архив: 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.011 c