Советы по Delphi

         

Обработка ошибок WinSock


Для работы любого из нижеследующего метода обработки исключительной ситуации необходимо, чтобы VCL узнал о возникновении самой ошибки. Если вызов Winsock ничего не возвращает, или он не обеспечивает информацией потомка TCustomWinSocket, который его вызвал, то механизма выполнения данного условия не существует.

Обработчик исключения OnError

Для организации ловушек исключительных ситуаций в потомке TCustomWinSocket один метод должен использоваться для обработки исключения OnError. Данный метод должен обрабатывать ограниченный набор условий, поскольку механизм, предусмотренный Winsock для событий-уведомителей, реагирует только на ограниченный список условий. Чтобы быть извещенным об исключительной ситуации, возникшей при работе Winsock, TCustomWinSocket регистрирует пользовательское сообщение CM_SocketMessage, посылаемое компоненту, а обработчик сообщения CMSocketMessage генерирует исключительную ситуацию. Сообщение регистрируется Winsock вызовом API WSASyncSelect. WSASyncSelect - запрос для уведемления о событиях чтения из сокета, записи, соединения, закрытия и акцептования. Если исключительная ситуация не событие чтения, записи, соединения, закрытия или акцептования, или CM_SocketMessage по любой причине не был послан Winsock, обработчик события не сработает.

Использование:

    procedure TChatForm.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); const
ErrorEvents: array[eeGeneral..eeAccept] of string = ( 'eeGeneral', 'eeSend',

'eeReceive', 'eeConnect', 'eeDisconnect', 'eeAccept' ); begin
ListBox1.Items.Add('ClientSocketError. TErrorEvent: ' +
ErrorEvents[ErrorEvent] + ' ErrorCode: ' + IntToStr(ErrorCode)); ErrorCode := 0; // исключение не генерируем end;

Определение:

    procedure TCustomWinSocket.CMSocketMessage(var Message: TCMSocketMessage);

function CheckError: Boolean; var ErrorEvent: TErrorEvent; ErrorCode: Integer; begin if Message.SelectError <> 0 then begin Result := False; ErrorCode := Message.SelectError; case Message.SelectEvent of FD_CONNECT: ErrorEvent := eeConnect; FD_CLOSE: ErrorEvent := eeDisconnect; FD_READ: ErrorEvent := eeReceive; FD_WRITE: ErrorEvent := eeSend; FD_ACCEPT: ErrorEvent := eeAccept; else ErrorEvent := eeGeneral; end; Error(Self, ErrorEvent, ErrorCode); if ErrorCode <> 0 then raise ESocketError.CreateFmt(sASyncSocketError, [ErrorCode]); end else Result := True; end;
begin
with Message do if
CheckError then case SelectEvent of FD_CONNECT: Connect(Socket); FD_CLOSE: Disconnect(Socket); FD_READ: Read(Socket); FD_WRITE: Write(Socket); FD_ACCEPT: Accept(Socket); end; end;

Обработка исключений Объектным Паскалем

Вы также можете поместить специфичный вызов в конструкцию try..except, или создать свой обработчик исключительных ситуаций на уровне приложения. Чтобы это работало, компонент должен иметь возможность быть уведомленным об возникновении исключительной ситуации, а чтобы исключение могло быть перехвачено, его необходимо сгенерировать.

Пример обработчика исключительных ситуаций на уровне приложения:

    TChatForm = class(TForm)

public procedure AppException(Sender: TObject; E: Exception); end;

implementation

procedure TChatForm.AppException(Sender: TObject; E: Exception);
begin
ListBox1.Items.Add('AppException: ' + E.Message); end;

procedure TChatForm.FormCreate(Sender: TObject);
begin
Application.OnException := AppException; end;

Пример конструкции Try..Except:

    with ClientSocket do
try
Active := True; except on E: Exception do ListBox1.Items.Add('В течение Try..except: ' + E.Message); end; end;

SocketErrorProc

Для вызовов, которые для проверки результата, возвращаемого WSAGetLastError, обычно используют функцию CheckSocketResult, ошибки могут быть обработаны программистом, определившим функцию, устанавливающую SocketErrorProc.

Использование:

    Interface

procedure
MySocketError(ErrorCode: Integer);

implementation

procedure MySocketError(ErrorCode: Integer);
begin
ShowMessage('MySocketError: ' + IntToStr(ErrorCode)); end;

procedure TChatForm.FormCreate(Sender: TObject);
begin
SocketErrorProc := MySocketError; end;

Определение:

    function CheckSocketResult(ResultCode: Integer; const Op: string):
Integer; begin
if
ResultCode <> 0 then begin Result := WSAGetLastError; if Result <> WSAEWOULDBLOCK then if Assigned(SocketErrorProc) then SocketErrorProc(Result) else raise ESocketError.CreateFmt(sWindowsSocketError, [SysErrorMessage(Result), Result, Op]); end else Result := 0; end;

Подсказка для SocketErrorProc:

    Unit ScktComp

SocketErrorProc обрабатывает ообщения об ошибках, которые были получены от Windows socket-соединения.

    threadvar SocketErrorProc: procedure (ErrorCode: Integer);

Описание: Назначаем значение SocketErrorProc для обработки сообщения об ошибке от вызова Windows socket API прежде, чем компонент поднимет исключение. Установка SocketErrorProc предотвращает socket-компонент от генерирования исключительной ситуации. SocketErrorProc - потоково-локальная переменная. Этим возможна обработка ошибки, возникающей при вызовах Windows socket API, осуществляемых в пределах единственного потока выполнения.

Обработка исключительных ситуаций в потомках TCustomWinSocket [001966]



Содержание раздела