-
Здравствуйте.
-
Хочу запустить сервер в потоке, который в свою очередь должен создавать отдельные потоки для каждого соединения. Использую наследника от 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; ---------------
-
где и как ты создаешь и инициализируешь слушающий sSocket ?
-
функция инициализации сокета запускается в основной программе, поток создается приостановленным и приступает к работе после инициализации сокета. ------- 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;
-
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.
-
cSocket:=accept(sSocket,@cAddr,@cAddrSize);
if cSocket<>INVALID_SOCKET then begin
Write('+');
CloseSocket(cSocket);
end
else write('Accept() failed with error code ', WSAGetLastError);
-
ошибка 10014 нашел такое описание ошибки: --- Система обнаружила недопустимый указатель адреса при попытке использовать в вызове аргумент указателя. ---
-
в некоторых статьях упоминается информация, что для потока нужно хитро расшаривать переменные (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;
-
> accept(sSocket,@cAddr,@cAddrSize);
Имхо, собаки тут не нужны.
-
> у меня cSocket описан вот так:
с этого и надо было начинать) > нужно хитро расшаривать переменные (threadvar), которые > не описаны внутри потока
не надо ничего "хитро расшаривать" - это вообще из другой оперы. > cAddrSize:word;
Ты вот скажи , с какого перепугу у тебя word, если в прототипе function accept(s: TSocket; addr: PSockAddr; addrlen: PInteger): TSocket; stdcall;
?
-
> собаки тут не нужны
нужны.
-
полный абзац поменял word на integer и поток начал слушать :) вот уж не думал, что одинаковые переменные, единственное отличие которых заключается в интерпретации последнего бита, будут настолько не совместимы. и word и integer занимают два байта, а Delphi оказывается ведет учет типа во всех ячейках памяти.
получается, что я не смогу в переменную типа pointer или ^word присвоить значение переменной типа ^integer?
-
> одинаковые переменные
Одинаковыми они были при царе горохе.
-
> Сергей М. © (02.03.12 17:46) [10] > > > > собаки тут не нужны > > > нужны. >
Точно. Просто я помнил описание accept из ICS Там было function accept(s: TSocket; var addr: TSockAddr; var addrlen: Integer): TSocket;
-
тип word указал на случай, если вдруг размер поля адреса окажется больше MaxInt (что бы отрицательный размер не получился) да и как-то непривычно в качестве параметра, обозначающего размер блока памяти, ставить переменную, которая может быть отрицательной.
Огромная благодарность Сергею М. за помощь (а то уже вариантов 10 серверов написал и у всех та же проблема; ловил уже себя на желании разбить ноут об стенку :) , а тут заработало, ноут выжил)
-
> Одинаковыми они были при царе горохе
Эт точно)
-
> получается, что я не смогу в переменную типа pointer или > ^word присвоить значение переменной типа ^integer?
Не получается.
Переменной типа pointer и типа word расчудесно присваивается значение переменной типа ^intrger, так же как и значение типа ^хз_что_и_сбоку_фантик, ибо все они указательные типы.
-
> и типа word
и типа ^word
-
> Сергей М. (02.03.2012 21:50:17) [17]
При этом прекрасно портятся два байта за ^word или читается не то
-
> Anatoly Podgoretsky © (02.03.12 22:41) [18]
А это уже другая песня)
-
> Сергей М. (02.03.2012 22:42:19) [19]
Так задача указателя указывать (правильно)
-
> Anatoly Podgoretsky © (02.03.12 23:16) [20]
Указывать правильно - задача не указателя, а программиста, использующего указатель)
На заборе, вестимо, может быть все что угодно написано, хотя там дрова лежат)
|