Erlang по-русски. Форум » Erlang

Рейтинг топика

Всего проглосовало:
Ваша оценка:

Как посылать сообщения?

(9 posts)

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

    Отправлено 11 мес. назад #
  2. Обработку данных можно также выделить (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 мес. назад #
  3. По-моему в примере в ф-и loop1 должна вызываться она сама, а не loop. Все равно не понимаю как процесс, который занимается обработкой будет принимать сообщения, пусть даже и не от сервера, а от функции на своем компьютере.
    Я пишу брутфорсер на ерланге). Понимаю что будут проблемы с производительностью, но это не имеет значения для курсового(все что угодно лишь бы распределенное). Брутфорсер выбрал из-за простоты реализации(произведение матриц намного сложнее).
    Пароли подбираются одновременно к нескольким хешам, с которыми сравниваются хеши подбираемых паролей.
    Вроде продумал протокол. Если клиент нашел пароль, он шлет сообщение серверу {found,Hash,Pass}, а он, в свою очередь, рассылает сообщения другим клиентам что хеш нужно удалить из списков{delHash,Hash,self()}. Если кончился диапазон, клиент также шлет сообщение{notfound,self()} и сервер отвечает новым диапазоном {task,Range,self()}. Нужно, не начиная с начала диапазона, удалить хеш и продолжить перебор. Если вычислителей несколько у каждого нужно укоротить список хешей.

    Отправлено 11 мес. назад #
  4. В процессе который будет заниматься обработкой, в конце добавить конструкцию вида:

    receive
    {interrupt} ->
    ... обработка прерывания ...
    after 0 ->
    ... вызов нового такта цикла обработки ...
    end.

    Это обеспечит проверку на прерывание перед началом каждого такта обработки.

    Отправлено 11 мес. назад #
  5. Но если у меня вся обработка в определителе списка?

    Отправлено 11 мес. назад #
  6. Код покажи

    Отправлено 11 мес. назад #
  7. Кода еще нет - не хватает времени. Вообще люблю сначала представить всю структуру программы в уме/на бумаге и только затем писать.
    Проблему с определителем решил. Можно перебирать в определителе только 2-3 последних символа, потом по совету 3BEP добавить receive. Это не должно повлиять на производительность.

    Отправлено 11 мес. назад #
  8. Отказался от идеи посылки сообщений о вычисленном хеше клиентам. Написал код сервера и набросок кода клиента. Сервер запускается без проблем, но клиент не может к нему подсоединиться - выдает ошибку.
    Запуск сервера

    
    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 мес. назад #
  9. Естественно оно выдаст undef - функция-то не экспортирована, поэтому spawn её не видит.

    Отправлено 9 мес. назад #

RSS экспорт этой темы

Отправить сообщение

Вы должны войти в систему, чтобы оставлять сообщения.