Ошибка при приеме данных после GetQueuedCompletionStatus

Тема в разделе "WASM.WIN32", создана пользователем SnugForce, 24 янв 2006.

  1. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Регистрация:
    2 май 2005
    Сообщения:
    373
    Адрес:
    Из домУ
    Там правда работа с сокетами, но думаю, что ошибка в применении порта завершения, а понять не могу где, параметры передаю правильные. А она выдает:

    Error -> WSARecv: 10045

    Предпринятая операция не поддерживается для выбранного типа объекта



    Код (Text):
    1.  
    2. program Project1;
    3. {$APPTYPE CONSOLE}
    4. uses
    5.   SysUtils, Windows, Winsock2;
    6. const
    7.   SRV_DATA_SEND = 1;
    8.   SRV_DATA_RECV = 2;
    9.   MSG_HELLO = 'Hello, client!';
    10. type
    11.   TPerHandleData = record
    12.     lpOverlapped: TOverlapped;
    13.     PBufRead: WSABUF;
    14.     PBufWrite: WSABUF;
    15.     BufRead: array [0..99] of char;
    16.     BufWrite: array [0..99] of char;
    17.     Client: TSockAddr;
    18.     Sock: TSocket;
    19.     BytesSend: Cardinal;
    20.     BytesRecv: Cardinal;
    21.     OperationType: Cardinal;
    22.     TotalBytes: Cardinal;
    23.   end;
    24.   PPerHandleData = ^TPerHandleData;
    25.   TData = record
    26.     Sock: TSocket;
    27.   end;
    28.   PData = ^TData;
    29.  
    30. var
    31.   wsd: TWSAData;
    32.   csWriteConsole: TRTLCriticalSection;
    33.   hServerThread: THandle;
    34.   t: Cardinal;
    35.  
    36. procedure MyWriteln(const S: string);
    37. var
    38.   NewStr: string;
    39. begin
    40.   SetLength(NewStr, Length(S));
    41.   CharToOem(PChar(S), PChar(NewStr));
    42.   Writeln(NewStr);
    43. end;
    44.  
    45. // Вывод сообщения об ошибке с ее кодом и инф строкой
    46. procedure FormatError(NameFunction: string);
    47. var
    48.   ErrorCode: Integer;
    49. begin
    50.   ErrorCode := GetLastError();
    51.   EnterCriticalSection(csWriteConsole);
    52.   MyWriteln('Error ->  ' + NameFunction +': ' + IntToStr(ErrorCode));
    53.   MyWriteln(SysErrorMessage(ErrorCode));
    54.   LeaveCriticalSection(csWriteConsole);
    55. end;
    56.  
    57. // Вывод диагностического сообщения
    58. procedure FormatDiag(Mes: string);
    59. begin
    60.   EnterCriticalSection(csWriteConsole);
    61.   MyWriteln(Mes);
    62.   LeaveCriticalSection(csWriteConsole);
    63. end;
    64.  
    65. // Рабочий поток порта завершения
    66. function CompletionPortThread(p: pointer): integer;
    67. var
    68.   CompletionPort: THandle;
    69.   BytesTransferred: Cardinal;
    70.   pDt: PData;
    71.   pPer: PPerHandleData;
    72.   Flags: Cardinal;
    73. begin
    74.   FormatDiag('Thread start.');
    75.   CompletionPort := THandle(p);
    76.   while true do
    77.   begin
    78.  
    79.     if not GetQueuedCompletionStatus(CompletionPort, BytesTransferred, DWORD(pDt),
    80.                                  POverlapped(pPer), INFINITE)  then
    81.     begin
    82.       FormatError('GetQueuedCompletionStatus');
    83.       Result := 0;
    84.       Exit;
    85.     end;
    86.  
    87.     // Клиент отключился
    88.     if BytesTransferred = 0 then
    89.     begin
    90.       FormatDiag('ClientDisconnect');
    91.       CloseSocket(pDt^.Sock);
    92.       Dispose(pDt);
    93.       Dispose(pPer);
    94.       Continue;
    95.     end;
    96.     if pPer^.BytesSend > 0 then
    97.     begin
    98.       FormatDiag('Buffer sended.');
    99.       pPer^.BytesSend := 0;
    100.     end
    101.     else
    102.     begin
    103.       FormatDiag('Buffer recv.');
    104.       //FormatDiag(pPer^.PBufRead.buf);
    105.       pPer^.BytesRecv := 0;
    106.       ZeroMemory(@pPer^.lpOverlapped, sizeof(TOverlapped));
    107.       ZeroMemory(pPer^.PBufRead.buf, pPer^.PBufRead.len);
    108.       FormatError('WSARecv');
    109.       Flags := 0;
    110.       if WSARecv(pDt^.Sock, @pPer^.PBufRead, 1, pPer^.BytesRecv, Flags, @pPer^.lpOverlapped, nil) = SOCKET_ERROR then
    111.         if WSAGetLastError <> ERROR_IO_PENDING then
    112.         begin
    113.           FormatError('WSARecv');
    114.           exit;
    115.         end;
    116.     end;
    117.   end;
    118. end;
    119.  
    120. // Проверка клиента внутри WSAAccept
    121. function TestClient(lpCallerId: LPWSABUF; lpCallerData : LPWSABUF;
    122.                     lpSQOS,lpGQOS : LPQOS; lpCalleeId,lpCalleeData : LPWSABUF;
    123.                     g : GROUP; dwCallbackData : DWORD ) : Integer;
    124. begin
    125.   FormatDiag(' !!! TestClient');
    126.   Result := CF_ACCEPT;
    127. end;
    128.  
    129. // Ожидание нового клиента и связывание с портом завершения
    130. function ServerThread(p: pointer): integer;
    131. var
    132.   hCompletionPort: Thandle;
    133.   SysInfo: TSystemInfo;
    134.   hCompletionPortThread: THandle;
    135.   iCounter: Integer;
    136.   t: Cardinal;
    137.   pDt: PData;
    138.   pPer: PPerHandleData;
    139.  
    140.   sock, s: TSocket;
    141.   Addr, Client: TSockAddr;
    142.   Cond: BOOL;
    143.   Flags: Cardinal;
    144. begin
    145.   // Создание порта завершения
    146.   hCompletionPort := CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
    147.   if hCompletionPort = 0 then
    148.   begin
    149.     FormatError('CreateIoCompletionPort');
    150.     Readln;
    151.     Result := 1;
    152.     Exit;
    153.   end;
    154.  
    155.   // Получаем кол-во процессоров в системе и
    156.   // соот-но ему создаем рабочи потоки для обработки порта заверешния
    157.   // Необходимо подобрать это число потоков т.к.
    158.   // при обработке данных очередь потока будет ждать
    159.   GetSystemInfo(SysInfo);
    160.   //FormatDiag('Number Of Processors ' + SysInfo.dwNumberOfProcessors);
    161.   for iCounter := 0 to SysInfo.dwNumberOfProcessors - 1 do
    162.   begin
    163.     hCompletionPortThread := BeginThread(nil, 0, @CompletionPortThread,
    164.                                          pointer(hCompletionPort), 0, t);
    165.     if hCompletionPortThread <> 0 then
    166.       CloseHandle(hCompletionPortThread)
    167.     else
    168.       FormatError('CreateThread');
    169.   end;
    170.   // Заполнение необх структур для слуш сокета
    171.   Addr.sin_family := AF_INET;
    172.   Addr.sin_port := htons(DWORD(p));
    173.   Addr.sin_addr.S_addr := 0;
    174.   // Создание сокета с возм перекрытого IO
    175.   sock := WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, nil, 0, WSA_FLAG_OVERLAPPED);
    176.   if sock = INVALID_SOCKET then
    177.     FormatError('WSASocket');
    178.   if bind(sock, @Addr, sizeof(Addr)) <> 0 then
    179.     FormatError('bind');
    180.   // Устанавливаем обработку клиента до посыла ему подтверждения соединения
    181.   Cond := True;
    182.   if setsockopt(sock, SOL_SOCKET, SO_CONDITIONAL_ACCEPT,
    183.              PChar(@Cond), sizeof(Cond)) <> 0 then
    184.     FormatError('setsockopt');
    185.   // Слушай сокет!
    186.   if listen(sock, 65536) <> 0 then
    187.     FormatError('listen');
    188.   FormatDiag('Wait new client on ' + IntToStr(integer(p)) + ' port...');
    189.   // Цикл приема новых клиентов
    190.   while true do
    191.   begin
    192.     s := WSAAccept(sock, @Client, nil, @TestClient, 0);
    193.     if s = INVALID_SOCKET then
    194.     begin
    195.       FormatError('WSAAccept');
    196.       Continue;
    197.     end;
    198.     FormatDiag('New client');
    199.     New(pDt);
    200.     pDt^.Sock := s;
    201.     if CreateIoCompletionPort(s, hCompletionPort, DWORD(pDt), 0) = 0 then
    202.     begin
    203.       FormatError('CreateIoCompletionPort');
    204.       Result := 1;
    205.       exit;
    206.     end;
    207.     New(pPer);
    208.     ZeroMemory(pPer, sizeof(TPerHandleData));
    209.     pPer^.Sock := s;
    210.     pPer^.BytesSend := 0;
    211.     pPer^.BytesRecv := 0;
    212.     pPer^.PBufWrite.buf := MSG_HELLO;
    213.     pPer^.PBufWrite.len := length(MSG_HELLO);
    214.     pPer^.PBufRead.buf := pPer^.BufRead;
    215.     pPer^.PBufRead.len := sizeof(pPer^.BufRead);
    216.     if WSARecv(s, @(pPer^.PBufRead), 1, pPer^.BytesRecv, Flags, @pPer^.lpOverlapped, nil) = SOCKET_ERROR then
    217.       if WSAGetLastError <> ERROR_IO_PENDING then
    218.       begin
    219.         FormatError('WSARecv');
    220.         exit;
    221.       end;
    222.   end;
    223.   closesocket(sock);
    224. end;
    225.  
    226. begin
    227.   SetConsoleTitle('Code by SnugForce/ 2006');
    228.   InitializeCriticalSection(csWriteConsole);
    229.  
    230.   if WSAStartup(MAKEWORD(2,2), wsd) <> 0 then
    231.   begin
    232.     FormatError('WSAStartup');
    233.     Readln;
    234.     Exit;
    235.   end;
    236.  
    237.   hServerThread := BeginThread(nil, 0, @ServerThread, pointer(3000), 0, t);
    238.   if hServerThread <> 0 then
    239.     CloseHandle(hServerThread)
    240.   else
    241.   begin
    242.     FormatError('CreateThread');
    243.     Exit;
    244.   end;
    245.   while true do
    246.   begin
    247.     readln;
    248.   end;
    249.   DeleteCriticalSection(csWriteConsole);
    250.   WSACleanup();
    251. end.
    252.  
     
  2. NullSessi0n

    NullSessi0n New Member

    Публикаций:
    0
    Регистрация:
    20 янв 2006
    Сообщения:
    322
    И обязательно надо на Delphi писать? Мне он уж давно не нравится, да и форум ассемблерный.

    Проверь состояние после вызова функции, указанной тобой в топике. Скорее всего ты сунул ей не тот параметр. И это вообще твой текст?
     
  3. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Регистрация:
    2 май 2005
    Сообщения:
    373
    Адрес:
    Из домУ
    NullSessi0n

    C примера на C++ перевел.

    Ведь первый раз WSARecv вызывается удачно... Потом выдает ошибку. дескриптор сокета правильный, а что за объект тогда?
     
  4. SnugForce

    SnugForce New Member

    Публикаций:
    0
    Регистрация:
    2 май 2005
    Сообщения:
    373
    Адрес:
    Из домУ
    Нашел ошибку. Спасибо, что не ответили (я серьезно)...

    А может кто скажет тогда как определить какая операция была завершена? Ведь если произошло несколько вызовов ввода и вывода и не известно, которая операция завершится, то как узнать в обработке порта завершения какая операция была завершена - чтение или запись?