LAN Web TCP Delphi

Title: Handling Winsock errors
Question: For any of the following exception handling methods to work, the VCL must in some way become aware that an error condition exists. If a call to the Winsock does not return, or does not provide information to the TCustomWinSocket descendant that called it, then there is no mechanism to handle the condition. OnError exception handler.
Answer:
One method for trapping exception conditions in a descendant of TCustomWinSocket is to use an OnError exception handler. This method will only handle a limited set of conditions because the mechanism provided by the Winsock for event notification only reacts to a limited list of conditions. To be notified of an exception condition within the Winsock, TCustomWinSocket registers user message CM_SocketMessage to be sent to the component, and the CMSocketMessage message handler raises an exception. The message is registered with the Winsock by an API call to WSASyncSelect. WSASyncSelect is a request for event notification of socket read, writes, connect, close, and accept events. If the exception condition is not read, write, connect, close or accept, or if the CM_SocketMessage is not sent by the Winsock for any reason, the error handler will not fire.
Usage:
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; // don't raise an exception
end;
Definition:
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;
Object Pascal Exception Handling
You can also wrap a specific call in a try..except block or
setting an application level exception handler. For this to
work, the component must in some way become aware of the
exception condition and an exception must be raised for the
exception to be trapped here.
Example of Application Exception Handler:
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;
Example of Try..Except block:
with ClientSocket do
try
Active := True;
except
on E: Exception do
ListBox1.Items.Add('Try..except during open: ' + E.Message);
end;
end;
SocketErrorProc
For calls that use the CheckSocketResult function to check the
result returned by WSAGetLastError, errors can be handled in a
programmer defined function by setting the SocketErrorProc.
Usage:
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;
Defined:
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;
Help Text for SocketErrorProc:
Unit ScktComp
SocketErrorProc handles error messages that are received from a Windows socket
connection.
threadvar SocketErrorProc: procedure (ErrorCode: Integer);
Assign a value to SocketErrorProc to handle error messages
from Windows socket API calls before the socket component raises an
exception. Setting SocketErrorProc prevents the socket component from
raising an exception. SocketErrorProc is a thread-local variable. It
only handles errors that arise from the Windows socket API calls made within
a single execution thread.