// Connection.BytesLeft < 0 — строка прочитана частично
Inc(Connection.Offset, cdTransferred);
// Формируем буфер из непрочитанного остатка строки
Buf.Len:= Connection.BytesLeft;
Buf.Buf:= PChar(Connection.Msg) + Connection.Offset;
// Читаем остаток строки
Flags:= 0;
if WSARecv(Connection.ClientSocket, @Buf, 1, NumBytes, Flags,
@Connection.Overlapped, ReadMsgCompleted) = SOCKET_ERROR then
begin
if WSAGetLastError <> WSA_IO_PENDING then
begin
ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +
' — ошибка при чтении строки: ' + GetErrorString);
ServerForm.RemoveConnection(Connection);
end;
end;
end;
end;
// Функция SendMsgCompleted используется в качестве функции завершения
// для перекрытой отправки строки.
// Во многом она аналогична функции ReadLenCompleted
procedure SendMsgCompleted(dwError: DWORD; cdTransferred: DWORD; lpOverlapped: PWSAOverlapped; dwFlags: DWORD); stdcall;
var
Connection: PConnection;
Buf: TWSABuf;
NumBytes, Flags: DWORD;
begin
Connection:= ServerForm.GetConnectionByOverlapped(lpOverlapped);
if Connection = nil then
begin
ServerForm.AddMessageToLog(
'Внутренняя ошибка программы — не найдено соединение');
Exit;
end;
if dwError <> 0 then
begin
ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +
' — ошибка при отправке строки: ' + GetErrorString(dwError));
ServerForm.RemoveConnection(Connection);
Exit;
end;
Dec(Connection.BytesLeft, cdTransferred);
if Connection.BytesLeft < 0 then
begin
ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +
' — внутренняя ошибка программы: отправлено больше байтов, ' +
'чем ожидалось');
ServerForm.RemoveConnection(Connection);
end
else if Connection.BytesLeft = 0 then
begin
// Строка отправлена целиком. Выводим сообщение об этом.
ServerForm.AddMessageToLog('Клиенту ' + Connection.ClientAddr +
' отправлена строка: ' + Connection.Msg);
// Очищаем строку, чтобы зря не занимала память
Connection.Msg:= '';
// Теперь будем снова читать длину строки
Connection.Offset:= 0;
Connection.BytesLeft:= SizeOf(Integer);
// Читать будем в Connection.MsgSize
Buf.Len:= Connection.BytesLeft;
Buf.Buf:= @Connection.MsgSize;
Flags:= 0;
if WSARecv(Connection.ClientSocket, @Buf, 1, NumBytes, Flags,
@Connection.Overlapped, ReadLenCompleted) = SOCKET_ERROR then
begin
if WSAGetLastError <> WSA_IO_PENDING then
begin
ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +
' — ошибка при чтении длины строки: ' + GetErrorString);
ServerForm.RemoveConnection(Connection);
end;
end;
end
else
begin
// Строка отправлена не полностью
Inc(Connection.Offset, cdTransferred);