Там правда работа с сокетами, но думаю, что ошибка в применении порта завершения, а понять не могу где, параметры передаю правильные. А она выдает: Error -> WSARecv: 10045 Предпринятая операция не поддерживается для выбранного типа объекта Код (Text): program Project1; {$APPTYPE CONSOLE} uses SysUtils, Windows, Winsock2; const SRV_DATA_SEND = 1; SRV_DATA_RECV = 2; MSG_HELLO = 'Hello, client!'; type TPerHandleData = record lpOverlapped: TOverlapped; PBufRead: WSABUF; PBufWrite: WSABUF; BufRead: array [0..99] of char; BufWrite: array [0..99] of char; Client: TSockAddr; Sock: TSocket; BytesSend: Cardinal; BytesRecv: Cardinal; OperationType: Cardinal; TotalBytes: Cardinal; end; PPerHandleData = ^TPerHandleData; TData = record Sock: TSocket; end; PData = ^TData; var wsd: TWSAData; csWriteConsole: TRTLCriticalSection; hServerThread: THandle; t: Cardinal; procedure MyWriteln(const S: string); var NewStr: string; begin SetLength(NewStr, Length(S)); CharToOem(PChar(S), PChar(NewStr)); Writeln(NewStr); end; // Вывод сообщения об ошибке с ее кодом и инф строкой procedure FormatError(NameFunction: string); var ErrorCode: Integer; begin ErrorCode := GetLastError(); EnterCriticalSection(csWriteConsole); MyWriteln('Error -> ' + NameFunction +': ' + IntToStr(ErrorCode)); MyWriteln(SysErrorMessage(ErrorCode)); LeaveCriticalSection(csWriteConsole); end; // Вывод диагностического сообщения procedure FormatDiag(Mes: string); begin EnterCriticalSection(csWriteConsole); MyWriteln(Mes); LeaveCriticalSection(csWriteConsole); end; // Рабочий поток порта завершения function CompletionPortThread(p: pointer): integer; var CompletionPort: THandle; BytesTransferred: Cardinal; pDt: PData; pPer: PPerHandleData; Flags: Cardinal; begin FormatDiag('Thread start.'); CompletionPort := THandle(p); while true do begin if not GetQueuedCompletionStatus(CompletionPort, BytesTransferred, DWORD(pDt), POverlapped(pPer), INFINITE) then begin FormatError('GetQueuedCompletionStatus'); Result := 0; Exit; end; // Клиент отключился if BytesTransferred = 0 then begin FormatDiag('ClientDisconnect'); CloseSocket(pDt^.Sock); Dispose(pDt); Dispose(pPer); Continue; end; if pPer^.BytesSend > 0 then begin FormatDiag('Buffer sended.'); pPer^.BytesSend := 0; end else begin FormatDiag('Buffer recv.'); //FormatDiag(pPer^.PBufRead.buf); pPer^.BytesRecv := 0; ZeroMemory(@pPer^.lpOverlapped, sizeof(TOverlapped)); ZeroMemory(pPer^.PBufRead.buf, pPer^.PBufRead.len); FormatError('WSARecv'); Flags := 0; if WSARecv(pDt^.Sock, @pPer^.PBufRead, 1, pPer^.BytesRecv, Flags, @pPer^.lpOverlapped, nil) = SOCKET_ERROR then if WSAGetLastError <> ERROR_IO_PENDING then begin FormatError('WSARecv'); exit; end; end; end; end; // Проверка клиента внутри WSAAccept function TestClient(lpCallerId: LPWSABUF; lpCallerData : LPWSABUF; lpSQOS,lpGQOS : LPQOS; lpCalleeId,lpCalleeData : LPWSABUF; g : GROUP; dwCallbackData : DWORD ) : Integer; begin FormatDiag(' !!! TestClient'); Result := CF_ACCEPT; end; // Ожидание нового клиента и связывание с портом завершения function ServerThread(p: pointer): integer; var hCompletionPort: Thandle; SysInfo: TSystemInfo; hCompletionPortThread: THandle; iCounter: Integer; t: Cardinal; pDt: PData; pPer: PPerHandleData; sock, s: TSocket; Addr, Client: TSockAddr; Cond: BOOL; Flags: Cardinal; begin // Создание порта завершения hCompletionPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0); if hCompletionPort = 0 then begin FormatError('CreateIoCompletionPort'); Readln; Result := 1; Exit; end; // Получаем кол-во процессоров в системе и // соот-но ему создаем рабочи потоки для обработки порта заверешния // Необходимо подобрать это число потоков т.к. // при обработке данных очередь потока будет ждать GetSystemInfo(SysInfo); //FormatDiag('Number Of Processors ' + SysInfo.dwNumberOfProcessors); for iCounter := 0 to SysInfo.dwNumberOfProcessors - 1 do begin hCompletionPortThread := BeginThread(nil, 0, @CompletionPortThread, pointer(hCompletionPort), 0, t); if hCompletionPortThread <> 0 then CloseHandle(hCompletionPortThread) else FormatError('CreateThread'); end; // Заполнение необх структур для слуш сокета Addr.sin_family := AF_INET; Addr.sin_port := htons(DWORD(p)); Addr.sin_addr.S_addr := 0; // Создание сокета с возм перекрытого IO sock := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, nil, 0, WSA_FLAG_OVERLAPPED); if sock = INVALID_SOCKET then FormatError('WSASocket'); if bind(sock, @Addr, sizeof(Addr)) <> 0 then FormatError('bind'); // Устанавливаем обработку клиента до посыла ему подтверждения соединения Cond := True; if setsockopt(sock, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, PChar(@Cond), sizeof(Cond)) <> 0 then FormatError('setsockopt'); // Слушай сокет! if listen(sock, 65536) <> 0 then FormatError('listen'); FormatDiag('Wait new client on ' + IntToStr(integer(p)) + ' port...'); // Цикл приема новых клиентов while true do begin s := WSAAccept(sock, @Client, nil, @TestClient, 0); if s = INVALID_SOCKET then begin FormatError('WSAAccept'); Continue; end; FormatDiag('New client'); New(pDt); pDt^.Sock := s; if CreateIoCompletionPort(s, hCompletionPort, DWORD(pDt), 0) = 0 then begin FormatError('CreateIoCompletionPort'); Result := 1; exit; end; New(pPer); ZeroMemory(pPer, sizeof(TPerHandleData)); pPer^.Sock := s; pPer^.BytesSend := 0; pPer^.BytesRecv := 0; pPer^.PBufWrite.buf := MSG_HELLO; pPer^.PBufWrite.len := length(MSG_HELLO); pPer^.PBufRead.buf := pPer^.BufRead; pPer^.PBufRead.len := sizeof(pPer^.BufRead); if WSARecv(s, @(pPer^.PBufRead), 1, pPer^.BytesRecv, Flags, @pPer^.lpOverlapped, nil) = SOCKET_ERROR then if WSAGetLastError <> ERROR_IO_PENDING then begin FormatError('WSARecv'); exit; end; end; closesocket(sock); end; begin SetConsoleTitle('Code by SnugForce/ 2006'); InitializeCriticalSection(csWriteConsole); if WSAStartup(MAKEWORD(2,2), wsd) <> 0 then begin FormatError('WSAStartup'); Readln; Exit; end; hServerThread := BeginThread(nil, 0, @ServerThread, pointer(3000), 0, t); if hServerThread <> 0 then CloseHandle(hServerThread) else begin FormatError('CreateThread'); Exit; end; while true do begin readln; end; DeleteCriticalSection(csWriteConsole); WSACleanup(); end.
И обязательно надо на Delphi писать? Мне он уж давно не нравится, да и форум ассемблерный. Проверь состояние после вызова функции, указанной тобой в топике. Скорее всего ты сунул ей не тот параметр. И это вообще твой текст?
NullSessi0n C примера на C++ перевел. Ведь первый раз WSARecv вызывается удачно... Потом выдает ошибку. дескриптор сокета правильный, а что за объект тогда?
Нашел ошибку. Спасибо, что не ответили (я серьезно)... А может кто скажет тогда как определить какая операция была завершена? Ведь если произошло несколько вызовов ввода и вывода и не известно, которая операция завершится, то как узнать в обработке порта завершения какая операция была завершена - чтение или запись?