Код:
procedure TServerClientThread.ClientExecute;
var
FDSet: TFDSet;
TimeVal: TTimeVal;
begin
while not Terminated and ClientSocket.Connected do
begin
FD_ZERO(FDSet);
FD_SET(ClientSocket.SocketHandle, FDSet);
TimeVal.tv_sec := 0;
TimeVal.tv_usec := 500;
if (select(0, @FDSet, nil, nil, @TimeVal) > 0) and not Terminated then
if ClientSocket.ReceiveBuf(FDSet, -1) = 0 then Break
else Synchronize(DoRead);
if (select(0, nil, @FDSet, nil, @TimeVal) > 0) and not Terminated then
Synchronize(DoWrite);
end;
end;
В компоненте ServerSocket вечно проверяется, есть ли буфер для чтения или записи, если есть для чтения - вызывают функцию его чтения.
Код:
function TCustomWinSocket.ReceiveBuf(var Buf; Count: Integer): Integer;
var
ErrorCode, iCount: Integer;
begin
Lock;
try
Result := 0;
if (Count = -1) and FConnected then
ioctlsocket(FSocket, FIONREAD, Longint(Result))
else begin
if not FConnected then Exit;
if ioctlsocket(FSocket, FIONREAD, iCount) = 0 then
begin
if (iCount > 0) and (iCount < Count) then
Count := iCount;
end;
Result := recv(FSocket, Buf, Count, 0);
if Result = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeReceive, ErrorCode);
Disconnect(FSocket);
if ErrorCode <> 0 then
raise ESocketError.CreateResFmt(@sWindowsSocketError,
[SysErrorMessage(ErrorCode), ErrorCode, 'recv']);
end;
end;
end;
finally
Unlock;
end;
end;
Если эту функцию я правильно понял, то получается, что если прочитать не удалось то клиента отключают со стороны сервера.
Тогда не удивительно, что функция для ASocket начинает возвращать ошибку - ведь ASocket это число, ссылка. Сам сокет уже закрыт сервером т.к. была ошибка чтения.
Почитал код ServerSocket - решил встроить такую же проверку в свой код.
Встроил. Вроде работает нормально. Спасибо NumLock, что направили на этот компонент. По умолчанию его в Delphi XE нету...