DWORD WINAPI loop_recv_proc(LPVOID) {
client = head->next;
while(1) {
client = client->next;
recv(client->client_s..............);
}
}
высоконагруженный сервер
У меня теоретический вопрос. Заранее спасибо тем, кто поймет меня и поможет советом.
Мне интересны высоконагруженные системы клиент-сервер. Для повышения своих знаний хочу разобрать такую вещь как мессенджеры (к примеру маил агент, icq).
Реализовал следующее. (кода под рукой нет, напишу вперемешку с русским)
Серверная часть создает поток, который сокеты всех клиентов, переведенные в неблокирующий режим, опрашивает на наличие данных.
Код:
Потом биндит свой серверный сокет и ждет accept (выделено жирным).
Код:
DWORD WINAPI auth_proc(LPVOID my_struct) {
прием логина_пароля от клиента;
поиск пользователя в базе ? my_class->AddClient(my_struct->client_s,..........);
выход;
}
int main() {
CreateThread(........, &loop_recv_proc, &my_class.........);
while(1) {
client_s = accept(accept_s, ........);
Client_Struct *my_struct = new Client_Struct();
my_struct->client_s = &client_s;
CreateThread(......., &auth_proc, &my_struct........);
}
}
прием логина_пароля от клиента;
поиск пользователя в базе ? my_class->AddClient(my_struct->client_s,..........);
выход;
}
int main() {
CreateThread(........, &loop_recv_proc, &my_class.........);
while(1) {
client_s = accept(accept_s, ........);
Client_Struct *my_struct = new Client_Struct();
my_struct->client_s = &client_s;
CreateThread(......., &auth_proc, &my_struct........);
}
}
Сокеты всех подключенных клиентов добавляются в связанную структуру, в которой есть указатели Prev и Next.
metka_na_budushee: Если клиент с id=1 передает сообщение клиенту с id=2, то осуществляется поиск по всем связанным структурам в поисках клиента с id=2 и на этот сокет передается сообщение.
Все работает, все отлично.
Думаю при увеличении клиентов запускать еще один процесс loop_recv_proc, чтобы циклы по сокетам пробегались быстрее.
Но, если клиентов станет еще больше, чем может обслужить один сервер, тогда допустим ставим еще одну машину.
Как тогда осуществить то, что в metke_na_budushee? Как найти по id сокет того, кто обслуживается на другом сервере (может их не один, а два или три) и передать ему сообщение?
Может я изначально неправильно строю систему?
Искал в интернете информацию - ничего такого не нашел...
Видимо правильнее будет, если будет сервер А, который принимает клиента на accept, авторизует его, передает ему ip самого наименее загруженного сервера (Б, В, Г, ....) и запоминает в БД кого и кому передал.
При обработке клиента в случае получении сообщения, обслуживающий сервер делает запрос в базу сервера А, узнает на каком сервере обслуживается клиент с id=2 и передает демону того сервера сообщение...
Но мне кажется что вариант с БД - это слишком медленно получится
Эту ситуацию можно как-то грамотнее реализовать?
мастер хранит список запущеных слейвов и, как вариант, чтобы увеличить производительность, при запуске нового слейва обновляет список серверов на всех слейвах.
При этом любой сервер при возникновении ситуации, когда один аккаунт пишет другому, ищет этот аккаунт у себя, если не находит - дергает другой сервер.
Цитата: cursor
Серверная часть создает поток, который сокеты всех клиентов, переведенные в неблокирующий режим, опрашивает на наличие данных.
Зачем?
Используй асинхронные сокеты. Их не надо опрашивать, они сами тебе скажут, когда данные будут готовы.
Цитата: cursor
Код:
while(1) {
client_s = accept(accept_s, ........);
Client_Struct *my_struct = new Client_Struct();
my_struct->client_s = &client_s;
CreateThread(......., &auth_proc, &my_struct........);
}
}
client_s = accept(accept_s, ........);
Client_Struct *my_struct = new Client_Struct();
my_struct->client_s = &client_s;
CreateThread(......., &auth_proc, &my_struct........);
}
}
У тебя сколько соединений столько и потоков?! Ужос...
Используй порты завершения.
Цитата: cursor
Сокеты всех подключенных клиентов добавляются в связанную структуру, в которой есть указатели Prev и Next.
list ? Зачем?
Используй map.
Цитата: cursor
Думаю при увеличении клиентов запускать еще один процесс loop_recv_proc, чтобы циклы по сокетам пробегались быстрее.
Этого вообще не надо.
Цитата: Green
Зачем?
Используй асинхронные сокеты. Их не надо опрашивать, они сами тебе скажут, когда данные будут готовы.
У тебя сколько соединений столько и потоков?! Ужос...
Используй порты завершения.
Используй асинхронные сокеты. Их не надо опрашивать, они сами тебе скажут, когда данные будут готовы.
У тебя сколько соединений столько и потоков?! Ужос...
Используй порты завершения.
Я вроде их и использую.. Это которые переводишь в ioctl?
Один отдельный поток. Он в цикле проверяет все сокеты по очереди на прием.
Во, то что нужно. Спасибо
Цитата: cursor
Я вроде их и использую.. Это которые переводишь в ioctl?
Один отдельный поток. Он в цикле проверяет все сокеты по очереди на прием.
Один отдельный поток. Он в цикле проверяет все сокеты по очереди на прием.
Нет.
асихронные != неблокирующие
Про ассинхронные смотри ф-ции WSA...
Про порты завершения тебе оксотник уже дал ссылочку.