Конференция "Сети" » Проблема с WSAAccept [D7, WinXP]
 
  • zsv (31.05.13 20:44) [0]
    День добрый , подскажите, что не так делаю...
    При выполнении DoAccept (разрешение на подключение клиента) даже не входит в Callback-функцию, а после выполнения DoAccept вообще вываливается "аккесс виол.."
    Сокет неблокирующий, DoAccept пытаюсь выполнить по сигналу эвента FD_ACCEPT, все (создание сокета,прослушивание и ожидание сигналов) делается в отдельном потоке, ф-ю CallBackAccept больше нигде не определял..


    function CallBackAccept(lpCallerId: LPWSABUF; lpCallerData : LPWSABUF; lpSQOS,lpGQOS : LPQOS; lpCalleeId,lpCalleeData : LPWSABUF;
       g : GROUP; dwCallbackData : DWORD ) : Integer; stdcall;
    begin
     Result:=CF_Accept;
    end;

    function TClientsEventsThread.DoAccept:integer;
    var tmpSocket: TSocket;
       i:integer;
    begin
      i:=SizeOf(FNPC.FSockAddrIn); Result:=0;
      tmpSocket:=WSAAccept(FSocket, FSockAddrIn, @i, CallBackAccept, 1);
      if tmpSocket=SOCKET_ERROR then begin
         Result:=WSAGetLastError;
      end;
    end;

  • zsv (01.06.13 11:42) [1]
    всем спасибо, разобрался...
    надо было:
      tmpSocket:=WSAAccept(FSocket, @FSockAddrIn, @i, CallBackAccept, 1);
    и еще пришлось соответственно исправлять winsock2.pas:
      function WSAAccept( s : TSocket; addr : PSockAddr; addrlen : PInteger;   lpfnCondition : LPCONDITIONPROC; dwCallbackData : DWORD ): TSocket; stdcall;
    старый код winsock2.pas:
      function WSAAccept( s : TSocket; addr : TSockAddr; addrlen : PInteger;   lpfnCondition : LPCONDITIONPROC; dwCallbackData : DWORD ): TSocket; stdcall;

    кстате, скачивал winsock2.pas с различных мест раз пять, везде был одинаковый неправильный вариант... Просьба, выложите пожалуйста правильный вариант этого модуля, может это у меня не одна ошибка...
    спасибо
  • zsv (01.06.13 13:30) [2]
    Вопрос в догонку:
    если я отклоняю запрос на подключение CF_Reject, то событие FD_ACCEPT на сервере возникает еще два раза, через каждые пол секунды и только после этого на клиенте возникает событие FD_CONNECT с ошибкой WSAECONNREFUSED. Почему три раза и как этим можно управлять?
    Спасибо
  • Сергей М. © (03.06.13 21:29) [3]

    > Почему три раза


    Видимо с ивентом ка-то криво работаешь ..
  • zsv (25.06.13 15:33) [4]
    День добрый, Мастера.. Проблема трех эвентов так и осталась. Вот код потока, который слушает сокет

    procedure TZsNPCMembers.Execute;
    //выполнение потока подключения/отключения клиентов
    var Evt: LongWord;
       e: TNPCErrorInfo;
       Events: array[0..1] of THandle;  //массив событий для выхода из ожидания для потока
       NetworkEvents:TWSANetworkEvents;
       i:integer;
       tmpSocket: TSocket;
    begin
     //опеределить события возобновления потока
     Events[0] := FInternalEvent; Events[1] := FWSAEvent;
     //выполнение
     while Not Terminated do begin
        Evt:=WSAWaitForMultipleEvents(2,@Events, false, WSA_INFINITE, False);
        case Evt of
        WAIT_OBJECT_0:      //внутреннее событие для отработки потока
             ResetEvent(Events[0]);
        WAIT_OBJECT_0 + 1:  //событие сокета подключение/отключение
             begin
                WSAEnumNetworkEvents(FSocket, Events[1], @NetworkEvents);
    //WriteToFile('qqq.txt', inttostr(MyGetTickCount)+IfThen(FNPC.FAppType=npcatClient,' Клиент',' Сервер')+' - неизвестное событие '+IntToStr(NetworkEvents.lNetworkEvents)+' - '+InttoStr(ErrorCode));
                //запрос на подключение
                if (FNPC.FAppType=npcatServer) And
                   (NetworkEvents.lNetworkEvents and FD_ACCEPT>0) then begin
                   i:=NetworkEvents.iErrorCode[FD_ACCEPT_Bit];
                   if i=0 then begin
                      //без ошибки
                      i:=SizeOf(FSockAddrIn);
                      tmpSocket:=WSAAccept(FSocket, @FSockAddrIn, @i, CallBackAccept, DWord(FNPC));
    WriteToFile('qqq.txt', inttostr(GetTickCount)+' Сервер. Запрос подключения1 '+IntToStr(WSAGetLastError));
                   end else begin
    WriteToFile('qqq.txt', inttostr(GetTickCount)+' Сервер. Запрос подключения2 '+IntToStr(i));
                   end;
                end;
                //подключение
                if (FNPC.FAppType=npcatClient) And
                   (NetworkEvents.lNetworkEvents and FD_CONNECT>0) then begin
                   i:=NetworkEvents.iErrorCode[FD_CONNECT_Bit];
                   sleep(100);
    WriteToFile('qqq.txt', inttostr(GetTickCount)+' Клиент. Подключение '+IntToStr(i));
                end;
             end;
        WAIT_FAILED:;       //ошибка
        WAIT_TIMEOUT:       //таймаут
        end;
     end;
    end;


    В этом коде конечно много чего осталось "за кадром", различные определения, типы и тд, но в целом алгоритм прослушки виден
    Могу выложить весь проект, но к сожалению форум не дает прикреплять файлы... Спасибо, надеюсь на помощь
  • Сергей М. © (25.06.13 22:34) [5]
  • zsv (27.06.13 10:39) [6]
    Это не мой случай. у меня принимается именно три эвента FD_ACCEPT если я отказываю в акцепте, и только после этого на клиенте появляется результат.
    Все это происходит если в коде есть установка SetSockOpt(Socket, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, @Cond, SizeOf(Cond)); Если этой установки нет, то эвент устанавливается один, не зависимо от того принимаю я акцепт или нет, а клиент получает ответ сразу о подключении...
  • Сергей М. © (27.06.13 20:12) [7]

    > три эвента FD_ACCEPT если я отказываю в акцепте


    А если не отказываешь и сразу же акцептируешь ?
    И нет ли других взведенных флагов кроме FD_ACCEPT ?
  • zsv (01.07.13 19:25) [8]
    если не отказываю - то больше FD_ACCEPT не появляется. Других взведенных флагов нет...
  • Сергей М. © (02.07.13 15:52) [9]
    А вот в примере из msdn

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms742219%28v=vs.85%29.aspx

    явно фигурирует ручной сброс просигналившего ивента, созданного вызовом WSACreateEvent и сигнал которого обнаружен при WSAWaitForMultipleEvents

    А у тебя нет ручного сброса...
  • han_malign (02.07.13 17:36) [10]

    > А у тебя нет ручного сброса...

    - мимо:
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms741572%28v=vs.85%29.aspx
    WSAEnumNetworkEvents function
    ...
    If the hEventObject parameter is not NULL, the indicated event object is also reset.

    другое дело, что:
    In the case of this function returning SOCKET_ERROR, the associated event object is not reset and the record of network events is not cleared.
  • Сергей М. © (02.07.13 17:59) [11]

    > han_malign   (02.07.13 17:36) [10]


    А нафига тогда в примере по моей ссылке стоит вызов WSAResetEvent() ?
    Типа "щоб було" на всякий пожарный случай, для пущей надежности - а ну как не сбросится сигнал ?


    > record of network events is not cleared.


    Ну это , как и я предполагаю, и есть причина "повторных сигналов" ..
    Но как тут можно умудриться передать null (или вообще там мусор ?) в кач-ве хендла ивента - не представляю.

    А то что нехило было бы анализировать результат вызова WSAWaitForMultipleEvents() на предмет SOCKET_ERROR, хотя бы на этапе отладки - это да, солидарен.
  • han_malign (03.07.13 08:11) [12]

    > А нафига тогда в примере по моей ссылке стоит вызов WSAResetEvent()?

    - потому что там overlapped WSARecv - WSAEnumNetworkEvents не используется...

    > анализировать результат вызова WSAWaitForMultipleEvents()

    - WSAEnumNetworkEvents... - результат Wait анализируется в case.
  • zsv (03.07.13 18:41) [13]
    WSAEnumNetworkEvents возвращает 0 во всех трех случаях :((( а я так надеялся... Может выложить весь проект, там только форма и код подключения.  Только не дает выкладывать из-за большого размера кода...
  • Alex Konshin © (18.07.13 04:54) [14]
    > zsv   (01.06.13 11:42) [1]
    > старый код winsock2.pas:
    >   function WSAAccept( s : TSocket; addr : TSockAddr; addrlen
    > : PInteger;   lpfnCondition : LPCONDITIONPROC; dwCallbackData
    > : DWORD ): TSocket; stdcall;
    >
    > кстате, скачивал winsock2.pas с различных мест раз пять,
    >  везде был одинаковый неправильный вариант... Просьба, выложите
    > пожалуйста правильный вариант этого модуля, может это у
    > меня не одна ошибка...
    > спасибо

    Не знаю, откуда ты качал, но у меня
    function WSAAccept( const s : TSocket; addr : PSockAddr; addrlen : PInteger; lpfnCondition : LPCONDITIONPROC; const dwCallbackData : DWORD ): TSocket; stdcall;


    Специально скачал у себя с сайта и перепроверил.
    http://home.earthlink.net/~akonshin/delphi_ru.htm
    сам файл тут http://home.earthlink.net/~akonshin/files/ws2rev4a.zip
    Насколько я понял, большинство вариантов winsock2 в сети и в последних версиях Delphi - переделки из моего, там обычно даже мой копирайт присутствует.  
    Вот, интересно, что в FPC 2.6.0 в файле мой копирайт есть, но баг присутствует... Наверно, в какой-то из предыдущих версий он был...
 
Конференция "Сети" » Проблема с WSAAccept [D7, WinXP]
Есть новые Нет новых   [118488   +59][b:0][p:0.003]