Не подскажете где можно почитать про создание многопользовательского сетевого сервера. Необходимо написать многопользовательский сервер, с которым будут работать несколько тысяч пользователей онлайн одновременно.
Направьте плиз в русло.. а то искал по нету, ничего не нашел :(
Хотябы самые азы...
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
17-12-2007 16:50 | Сообщение от автора вопроса
А каким образом можно высчитывать таймауты тогда ? =\ Ведь Select не вернет управление до тех пока указанное время не истечёт =\
Самое время Вам вплотную познакомиться с протоколами TCP/IP и с их виндовой реинкарнацией.
Живут же люди - сотни и даже тысячи компьютеров под рукой имеют!
то, что мы затронули - самая верхушка айсберга, а на освоение остального необходимы время и практика.
Разобрался (это насчет предыдущего поста). Но всеравно предел пользователей не как указано в MSDN 65 000 а всего около 33 000... В чем может быть фишка ?
наткнулся на статью в инете http://support.microsoft.com/kb/q196271/ сделал все как написано. при нажатии на "папочку" Parameters в RegEdit'е справа появляются парметры DataBasePath, DeadGWDetectDefault, DhcpDomain,DhcpNameServer, Domain и другие. К ним я добавил MaxUserPort (REG_DWORD) = 0x00065000(413696). Всеравно останавливается на порту 5000 (смотрел при помощи netstat -a). не помогает... что делать, а ? =\
Спасибо большое за помощь. Вот еще одна проблемка возникла. Тестил сервак и решил приконнектить к нему 50 000 клиентов одновременно. Примерно на 3900 клиенте он выдал следующее... ошибка WinSock при выполнении функции Connect ( к лиенте) WSAGetLasError = 10055 (WSAENOBUFS). не подскажете как этого избежать ?
Я упустил? Ну ладно, я так я:)) Для запуска потока используется самая обыкновенная функция, никаких особых параметров не требуется. В том числе вполне годится и TThread.
>>> у меня хватает знаний чтобы все это понять и освоить
А я и не говорил, что Вы не сможете в этом разобраться. Вот только то, что мы затронули - самая верхушка айсберга, а на освоение остального необходимы время и практика. Только это я и имел в виду.
Нет... у меня хватает знаний чтобы все это понять и освоить. Спасибо большое за разъяснения... А вот этот вопросик вы пропустили. При создании потока надо указывать процедуру в которой все это будет выполняться... данная процедура(функция) должна иметь какие-то специфические параметры для передачи в неё? Или просто обычная процедура ?
Я вот чего подумал - может Вам лучше использовать QueueUserWorkItem? Она, правда, использует некий усредненный алгоритм, который в большинстве случаев не обеспечивает максимальную загрузку процессоров, зато освобождает программиста от всех забот по управлению пулом, перекладывая их на систему.
>>>необходимо будет всеравно создать около 1000 потоков
Да что у Вас за гигантизм, ей-богу:(( Изначально рекомендуется подключать потоков в два раза больше, чем имеется процессоров. А далее нужно следить, если входная очередь непуста, а процессоры загружены не полностью, то можно добавить 1-2 потока и опять следить. А при полной нагрузке от добавления потоков только хуже будет.
Вы уверены, что не рановато взялись за задачу такого уровня?
type
POverlappedEx = ^TOverlappedEx;
TOverlappedEx = record
Ovp: TOverlapped;
Obj: Pointer;
end;
TCompletionPort = class
private
FMaxActiveThreads: Cardinal;
FHandle: THandle;
public
constructor Create(MaxActiveThreads: Cardinal = 0);
destructor Destroy;override;
function AddDevice(hDevice: THandle; CompletionKey: Cardinal): boolean;
function FreeDevice(hDevice: THandle): boolean;
function WaitCompletion(out NumBytes, CompKey: Cardinal;
out pOvp: POverlappedEx; TimeOut: Cardinal = INFINITE): boolean;
function SetCompletion(NumBytes, CompKey: Cardinal;
const Ovp: TOverlappedEx): boolean;
property Handle: THandle read FHandle;
property MaxActiveThreads: Cardinal read FMaxActiveThreads;
end;
implementation
uses
SysUtils;
{ TCompletionPort }
constructor TCompletionPort.Create(MaxActiveThreads: Cardinal);
begin
FMaxActiveThreads:= MaxActiveThreads;
FHandle:= CreateIoCompletionPort(INVALID_HANDLE_VALUE,
0 , 0, FMaxActiveThreads);
{$IFDEF VER140__}
if FHandle = 0 then RaiseLastOsError;
{$ELSE}
if FHandle = 0 then RaiseLastWin32Error;
{$ENDIF}
end;
function TCompletionPort.AddDevice(hDevice: THandle;
CompletionKey: Cardinal): boolean;
begin
Result:= CreateIoCompletionPort(hDevice, Handle, CompletionKey, 0) = FHandle;
end;
destructor TCompletionPort.Destroy;
begin
if FHandle <> 0 then CloseHandle(FHandle);
inherited;
end;
function TCompletionPort.FreeDevice(hDevice: THandle): boolean;
begin
Result:= CloseHandle(hDevice);
end;
function TCompletionPort.SetCompletion(NumBytes, CompKey: Cardinal;
const Ovp: TOverlappedEx): boolean;
begin
Result:= PostQueuedCompletionStatus(Handle, NumBytes, CompKey, @Ovp.Ovp);
end;
function TCompletionPort.WaitCompletion(out NumBytes, CompKey: Cardinal;
out pOvp: POverlappedEx; TimeOut: Cardinal = INFINITE): boolean;
begin
Result:= GetQueuedCompletionStatus(Handle,
NumBytes, CompKey, POverlapped(pOvp), TimeOut);
end;
end.
С AddDevice и FreeDevice, надеюсь, все понятно. Для подключения к пулу поток вызывает WaitCompletion. SetCompletion передает задание свободному потоку пула. В структуру OVERLAPPED добавлено поле, его можно использовать для собственных нужд, например для передачи объекта. Впрочем, это актуально при использовании AddDevice, при ручном вызове SetCompletion все параметры и поля можно использовать по своему усмотрению.
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, // the I/O completion port of interest
LPDWORD lpNumberOfBytesTransferred,// to receive number of bytes
// transferred during I/O
LPDWORD lpCompletionKey, // to receive file's completion key
LPOVERLAPPED *lpOverlapped, // to receive pointer to OVERLAPPED structure
DWORD dwMilliseconds // optional timeout value
);
LPOVERLAPPED свою структуру которая будет автоматически заполняться нужными данными. Никак не могу понять как это сделать... Не могли бы мне помочь?
Еще порыскал... кажись понял ))) Что получается, необходимо будет всеравно создать около 1000 потоков ( на всякий случай, ведь на сервере одновременно большое кол-во клиентов и если выполняющийся поток переходит в режим ожидания , например Select с таймаутом, то процессорное время отдается следующему потоку, а если их создать всего 2а (у меня 2а процессора) и они оба будут в ожидании то обработка следующего клиента затормозится ). При создании потока надо указывать процедуру в которой все это будет выполняться... не подскажете какие параметры должны быть у процедуры? А то везде указаны для Си а я в нём не особо шарю =\
не проще ли создать сразу 500 потоков и каждый из них будет обрабатывать по 20 клиентов. А если клиентов пока нет, то поток замораживается? Это ведь даже быстрее будет нежели 2а несчастных потока будут надрываться....
500? А че не 5000? Откуда возьмется это даже быстрее? У Вас от этого что, количество процессоров увеличится? Ну Бог в помощь...
Почитал я про CompletionPort но так и не понял его назначения. Этот порт завершения просто распределяет задачи? Необходим только один порт завершения на весь сервер, на который будут вешаться около 50 000 клиентов и он сам будет обрабатывать все запросы, мне надо лишь создать для него потоки(кол-во потоков = кол-во процессоров в системе)? Неясно что-то получается. не проще ли создать сразу 500 потоков и каждый из них будет обрабатывать по 20 клиентов. А если клиентов пока нет, то поток замораживается? Это ведь даже быстрее будет нежели 2а несчастных потока будут надрываться.... =\
Поискал по MSDN, тут на Королевстве и на Яндексе... нигде конкретно не говорится что такое IoCompletionPort и с чем его едят. Не подкинете ссылочку если таковые есть, пожалуйста.
Каждый поток на сервере обрабатывает по несколько клиентов, т.к. существует лимит потоков из-за превышения 2гигобайтного предела памяти выделенного приложению
Это вряд-ли. Вам уже намекали на IoCompletionPort.
По мне, так прежде всего нужно прикинуть исходя из назначения сервера минимальную, пиковую и среднюю нагрузку, то бишь количество одновременно обрабатываемых запросов и время на обработку запроса, а уже исходя из этого строить архитектуры. Причем вполне возможно, что стратегия при разных уровнях нагрузки потребуется совершенно разная - то есть потребуется механизм, оценивающий нагрузку и выбирающий ту или иную стратегию, как правило нет смысла иметь одновременно выполняющих обработку потоков больше, чем имеется процессоров в системе, и тут Completion Port будет как нельзя кстати. Вполне вероятно, что потребуется организовать очередь входящих запросов на моменты пиковой нагрузки. И, разумеется продумать защиту от перегрузки, т.е. ограничить длину этой очереди.
Далее уже можно думать о способах рапараллеливания, то есть об организации пула потоков, а без него Вам не обойтись
Мне необходимо написать сервер, который будет "вмещать" в себя около 50 000 пользователей онлайн. Я уже выбрал объектную базу. Каждый поток на сервере обрабатывает по несколько клиентов, т.к. существует лимит потоков из-за превышения 2гигобайтного предела памяти выделенного приложению (1н поток - 1н стек - 1н стек = 64 кб, и в сумме около 2000 потоков уже больше чем 2гб). Но мне необходимо организовать эту структуру. Где мне про это прочитать ?
Ребят... не такой я уж и дятел))) Это все знаю. В системно программировании уже сижу а вы меня сокеты учить отправляете)))
Я имею ввиду где можно прочитать про существующие модели таких серверов. так сказать хочу запастись информацией которая может мне помочь по ходу составления своей модели.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.