Пишу курсовой проект по созданию распределенной системы. Сервер должен принимать сообщения о готовности от клиентов, отсылать им данных на обработку, ждать результатов и затем слать новую порцию данных. Сервер может послать клиенту сообщение о том, что часть данных нужно отбросить, в любой момент.
Собственно проблема, как клиентам во время обработки данных принимать сообщения? Примеры из документации с пинг-понгом и мессенджером не помогают - там ведь процессы занимаются только обработкой сообщений.
Erlang по-русски. Форум » Erlang





Всего проглосовало:
Ваша оценка:
Как посылать сообщения?
(9 posts)-
Отправлено 11 мес. назад #
-
Обработку данных можно также выделить (
spawn) в другой процесс.То есть что-то типа
loop() -> Pid = spawn(процесс_который_будет заниматься_обработкой), loop1(Pid). loop1(Pid) -> receive {process, Data} -> Pid ! {process, Data}, loop(Pid); {interrupt} -> Pid ! {interrupt} loop(Pid); {exit} -> ok endОтправлено 11 мес. назад # -
По-моему в примере в ф-и loop1 должна вызываться она сама, а не loop. Все равно не понимаю как процесс, который занимается обработкой будет принимать сообщения, пусть даже и не от сервера, а от функции на своем компьютере.
Я пишу брутфорсер на ерланге). Понимаю что будут проблемы с производительностью, но это не имеет значения для курсового(все что угодно лишь бы распределенное). Брутфорсер выбрал из-за простоты реализации(произведение матриц намного сложнее).
Пароли подбираются одновременно к нескольким хешам, с которыми сравниваются хеши подбираемых паролей.
Вроде продумал протокол. Если клиент нашел пароль, он шлет сообщение серверу {found,Hash,Pass}, а он, в свою очередь, рассылает сообщения другим клиентам что хеш нужно удалить из списков{delHash,Hash,self()}. Если кончился диапазон, клиент также шлет сообщение{notfound,self()} и сервер отвечает новым диапазоном {task,Range,self()}. Нужно, не начиная с начала диапазона, удалить хеш и продолжить перебор. Если вычислителей несколько у каждого нужно укоротить список хешей.Отправлено 11 мес. назад # -
В процессе который будет заниматься обработкой, в конце добавить конструкцию вида:
receive
{interrupt} ->
... обработка прерывания ...
after 0 ->
... вызов нового такта цикла обработки ...
end.Это обеспечит проверку на прерывание перед началом каждого такта обработки.
Отправлено 11 мес. назад # -
Но если у меня вся обработка в определителе списка?
Отправлено 11 мес. назад # -
Код покажи
Отправлено 11 мес. назад # -
Кода еще нет - не хватает времени. Вообще люблю сначала представить всю структуру программы в уме/на бумаге и только затем писать.
Проблему с определителем решил. Можно перебирать в определителе только 2-3 последних символа, потом по совету 3BEP добавить receive. Это не должно повлиять на производительность.Отправлено 11 мес. назад # -
Отказался от идеи посылки сообщений о вычисленном хеше клиентам. Написал код сервера и набросок кода клиента. Сервер запускается без проблем, но клиент не может к нему подсоединиться - выдает ошибку.
Запуск сервераerl -sname brute Eshell V5.6 (abort with ^G) (brute@warez)1> server:start_server([{[1,2],[\"abcde\",\"abjasf\",\"ds\",\"1234\",\"12345\"]}]). User list = [] Task list = [{[1,2], [\"ds\",\"1234\",\"12345\"], [{1,5,\"abcde\"},{1,6,\"abjasf\"}]}] true (brute@warez)2> Запуск клиента erl -sname client Eshell V5.6 (abort with ^G) (client@warez)1> client:start_client(brute@warez). <0.37.0> =ERROR REPORT==== 14-Dec-2007::22:01:36 === Error in process <0.37.0> on node 'client@warez' with exit value: {undef,[{client,client,['brute@warez']}]} (client@warez)2> Код сервера <%%% Процесс сервера службы отправки сообщений %%% task[{[Hash],[RangeSymbol]}] -module(server). -export([start_server/1, server/1, server/2, next/1, next2/1]). -import(lists, [keymember/3, keysearch/3, keydelete/3, keyreplace/4, unzip/1, subtract/2, keyreplace/4, split/2, nth/2, map/2]). -include(\"mess_interface.hrl\"). %%% Список пользователей имеет формат [{ClientPid1, Hashes1, String1, Task1}, %%% {ClientPid22, Hashes22, String22, Task22}, ...] %%% Tasks = [ { [{I, L, Sym}], [Hash], ClientRange} ] %%% Task = {[Hash], Prefix, Range} %%% Result = [{Hash, Pass}] server(User_List, [{Prefix, Hashes, ClientRange}|Task_List]) -> io:format(\"User list = ~p~n Task list = ~p~n\", [User_List,[{Prefix, Hashes, ClientRange}|Task_List]]), receive #logon{client_pid=From} -> case keymember(From, 1, User_List) of true -> server(User_List, Task_List); false -> String = makeString(Prefix), From!{Hashes, String, ClientRange}, New_User_List=[{From, Hashes, String, ClientRange}|User_List], server(New_User_List, next([{Prefix, Hashes, ClientRange}|Task_List])) end; {'EXIT', From, _} -> {value, {_, Old_Hashes, String, Task} } = keysearch(From, 1, User_List), New_User_List=keydelete(From, 1, User_List), server(New_User_List, [makeTask(String, Old_Hashes, Task)|Task_List]); #notfound{client_pid=From} -> String = makeString(Prefix), New_User_List = keyreplace(From, 1, User_List, {From, Hashes, String, ClientRange}), From!{Hashes, String, ClientRange}, server(New_User_List, next([{Prefix, Hashes, ClientRange}|Task_List])); #found{client_pid=From, result=Result} -> {Solved_Hashes,_} = unzip(Result), New_Hashes=subtract(Hashes,Solved_Hashes), String = makeString(Prefix), From!{New_Hashes, String, ClientRange}, master!Result, New_User_List = keyreplace(From, 1, User_List, {From, Hashes, String, ClientRange}), server(New_User_List, next([{Prefix, New_Hashes, ClientRange}|Task_List])) end; server(_, []) -> exit(normal). server(Task_List) -> process_flag(trap_exit, true), New_Task_List = makeTasks(Task_List), server([], New_Task_List). %%% Запуск сервера start_server(Task_List) -> register(bruteserver, spawn(?MODULE, server, [Task_List])). makeTasks([{Hashes,Range}|Rest]) -> {ServerRange,ClientRange}=split(length(Range)-3, Range), [{Hashes, ClientRange, makeServerSide(ServerRange)}|makeTasks(Rest)]; makeTasks([]) -> []. makeString([{I,_,Sym}|Rest]) -> [nth(I,Sym)|makeString(Rest)]; makeString([]) -> []. makeTask(String, Old_Hashes, Task) -> {map(fun(x)->{1, 1, x} end, String), Old_Hashes, Task}. makeServerSide([Sym|Rest]) -> [{1, length(Sym), Sym}|makeServerSide(Rest)]; makeServerSide([]) -> []. next([{Prefix, _, _}|Rest]) -> {F,Pnext}=next2(Prefix), if F==1 -> [Pnext|Rest]; true -> Rest end. next2([])-> {0,[]}; next2([{I,L,Sym}|Rest])-> if I<L-> {1,[{I+1,L,Sym}|Rest]}; true-> {Flag,R}=next2(Rest), {Flag,[{1,L,Sym}|R]} end. > Код клиента <-module(client). -export([start_client/1, passes/2, pass/1]). client(Server_Node)-> {bruteserver, Server_Node}!{logon, self()}, receive A->io:format(\"client got ~p~n\",[A]) end. start_client(Server_Node)-> spawn(client, client, [Server_Node]). passes(Hashes,Range)-> [P||P<-pass(Range), H<-Hashes, erlang:md5(P)==H]. pass([X|Xs])-> [[A|B] || A<-X, B<-pass(Xs)]; pass([])-> [[]].>Отправлено 10 мес. назад # -
Естественно оно выдаст undef - функция-то не экспортирована, поэтому spawn её не видит.
Отправлено 9 мес. назад #
Отправить сообщение
Вы должны войти в систему, чтобы оставлять сообщения.