Конференция "WinAPI" » WinSock запуск сервера в потоке [D7]
 
  • vgbox © (02.03.12 15:18) [0]
    Здравствуйте.
  • vgbox © (02.03.12 15:31) [1]
    Хочу запустить сервер в потоке, который в свою очередь должен создавать отдельные потоки для каждого соединения.
    Использую наследника от TThread, инициализация WSA и создание сокета сервера вынес в отдельные процедуры и запускаются до старта потока.
    После запуска потока с сервером идет цикличный вывод открывающиейся и закрывающейся скобки, т.е. функция accept не ждет подключения (почему?), а сразу возвращает значение INVALID_SOCKET (почему?).
    Написал программу-клиент, которая успешно подключается к серверу, но сервер подключения не замечает, т.е. выдает все тот же INVALID_SOCKET (почему?). Плюс сервер не вывел на экран ниразу.
    ПС. Переменная sSocket объявлена в привате tServer и в потоке имеет то же значение, что при создании сокета (проверял пошагово).
    Прошу подсказать, что сделано неправильно или не сделано.
    Поток:
    ---------------
    procedure tServer.Execute;
    var
     cSocket:TSocket;
     cAddr:TSockAddr;
     cAddrSize:word;
    begin
     try
     while not Terminated do begin
       write('[');
       cAddrSize:=SizeOf(cAddr);
       cSocket:=accept(sSocket,@cAddr,@cAddrSize);
       if cSocket<>INVALID_SOCKET then begin
         write('+');
         CloseSocket(cSocket);
       end;
       write(']');
       Sleep(1000);
     end;
     finally
       write('*');
     end;
    end;
    ---------------
  • Сергей М. © (02.03.12 15:35) [2]
    где и как ты создаешь и инициализируешь слушающий sSocket ?
  • vgbox © (02.03.12 16:00) [3]
    функция инициализации сокета запускается в основной программе, поток создается приостановленным и приступает к работе после инициализации сокета.
    -------
    function tServer.InitSocket(MaxConnections:word):integer;
    var
     r:integer;
    begin
     try
       r:=-1;
       sSocket:=socket(AF_INET,SOCK_STREAM,0);
       if sSocket<>INVALID_SOCKET then begin
         r:=-2;
         sAddr.sin_family:=AF_INET;
         sAddr.sin_port:=htons(sPort);
         sAddr.sin_addr.S_addr:=INADDR_ANY;
         if bind(sSocket,sAddr, sizeof(sAddr))=0 then begin
           r:=-3;
           if listen(sSocket,MaxConnections)=0 then begin
             sMaxConnections:=MaxConnections;
             r:=0;
           end else CloseSocket(sSocket);
         end else CloseSocket(sSocket);
       end;
     finally
       InitSocket:=r;
     end;
    end;
  • vgbox © (02.03.12 16:08) [4]
    var
     s:tServer;
    begin
     { TODO -oUser -cConsole Main : Insert code here }
     s:=tServer.Create(5557);
     if s.InitWSA=0 then writeln('[+]InitWSA') else begin
       writeln('[-]InitWSA');
       exit;
     end;
     if s.InitSocket(1000)=0 then writeln('[+]InitSocket') else begin
       writeln('[-]InitSocket');
       exit;
     end;
     writeln('Starting server ...');
     s.Resume;
     readln;
     s.Terminate;
    end.
  • Сергей М. © (02.03.12 16:42) [5]
     
      cSocket:=accept(sSocket,@cAddr,@cAddrSize);
      if cSocket<>INVALID_SOCKET then begin
        Write('+');
        CloseSocket(cSocket);
      end
      else  write('Accept() failed with error code ', WSAGetLastError); // какой код отказа видишь ?


  • vgbox © (02.03.12 17:03) [6]
    ошибка 10014
    нашел такое описание ошибки:
    ---
    Система обнаружила недопустимый указатель адреса при попытке использовать в вызове аргумент указателя.
    ---
  • vgbox © (02.03.12 17:10) [7]
    в некоторых статьях упоминается информация, что для потока нужно хитро расшаривать переменные (threadvar), которые не описаны внутри потока.
    Может в описании переменной как-то ее расшарить?
    у меня cSocket описан вот так:
    ---
    type
     tServer=class(TThread)
       private
         WSAData:TWSAData;
         sSocket:TSocket;
         sAddr:TSockAddr;
         sPort:word;
         sMaxConnections:word;
       public
       constructor Create(Port:word);
       procedure Execute;override;
       function InitWSA:integer;
       function InitSocket(MaxConnections:word):integer;
     end;
  • Германн © (02.03.12 17:39) [8]

    > accept(sSocket,@cAddr,@cAddrSize);

    Имхо, собаки тут не нужны.
  • Сергей М. © (02.03.12 17:45) [9]

    > у меня cSocket описан вот так:


    с этого и надо было начинать)


    > нужно хитро расшаривать переменные (threadvar), которые
    > не описаны внутри потока


    не надо ничего "хитро расшаривать" - это вообще из другой оперы.


    > cAddrSize:word;


    Ты вот скажи , с какого перепугу у тебя word, если в прототипе

    function accept(s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; stdcall;


    ?
  • Сергей М. © (02.03.12 17:46) [10]

    > собаки тут не нужны


    нужны.
  • vgbox © (02.03.12 17:59) [11]
    полный абзац
    поменял word на integer и поток начал слушать :)
    вот уж не думал, что одинаковые переменные, единственное отличие которых заключается в интерпретации последнего бита, будут настолько не совместимы.
    и word и integer занимают два байта, а Delphi оказывается ведет учет типа во всех ячейках памяти.

    получается, что я не смогу в переменную типа pointer или ^word присвоить значение переменной типа ^integer?
  • Германн © (02.03.12 18:00) [12]

    >  одинаковые переменные

    Одинаковыми они были при царе горохе.
  • Германн © (02.03.12 18:03) [13]

    > Сергей М. ©   (02.03.12 17:46) [10]
    >
    >
    > > собаки тут не нужны
    >
    >
    > нужны.
    >

    Точно. Просто я помнил описание accept из ICS
    Там было
    function  accept(s: TSocket; var addr: TSockAddr; var addrlen: Integer): TSocket;

  • vgbox © (02.03.12 18:07) [14]
    тип word указал на случай, если вдруг размер поля адреса окажется больше MaxInt (что бы отрицательный размер не получился)
    да и как-то непривычно в качестве параметра, обозначающего размер блока памяти, ставить переменную, которая может быть отрицательной.

    Огромная благодарность Сергею М. за помощь (а то уже вариантов 10 серверов написал и у всех та же проблема; ловил уже себя на желании разбить ноут об стенку :) , а тут заработало, ноут выжил)
  • Сергей М. © (02.03.12 21:45) [15]

    > Одинаковыми они были при царе горохе


    Эт точно)
  • Сергей М. © (02.03.12 21:49) [16]

    > получается, что я не смогу в переменную типа pointer или
    > ^word присвоить значение переменной типа ^integer?


    Не получается.

    Переменной типа pointer и типа word расчудесно присваивается значение переменной типа ^intrger, так же как и значение типа ^хз_что_и_сбоку_фантик, ибо все они указательные типы.
  • Сергей М. © (02.03.12 21:50) [17]

    > и типа word


    и типа ^word
  • Anatoly Podgoretsky © (02.03.12 22:41) [18]
    > Сергей М.  (02.03.2012 21:50:17)  [17]

    При этом прекрасно портятся два байта за ^word или читается не то
  • Сергей М. © (02.03.12 22:42) [19]

    > Anatoly Podgoretsky ©   (02.03.12 22:41) [18]


    А это уже другая песня)
  • Anatoly Podgoretsky © (02.03.12 23:16) [20]
    > Сергей М.  (02.03.2012 22:42:19)  [19]

    Так задача указателя указывать (правильно)
  • Сергей М. © (02.03.12 23:32) [21]

    > Anatoly Podgoretsky ©   (02.03.12 23:16) [20]


    Указывать правильно - задача не указателя, а программиста, использующего указатель)

    На заборе, вестимо, может быть все что угодно написано, хотя там дрова лежат)
 
Конференция "WinAPI" » WinSock запуск сервера в потоке [D7]
Есть новые Нет новых   [134430   +4][b:0][p:0.002]