DedSec Project

Erlang — Αναλυτικός οδηγός εξάσκησης — DedSec Project

Erlang — αναδρομή και αντιστοίχιση προτύπων Δημιούργησε πραγματικό module Αποθήκευσε ως sums.erl, κάλεσε c(sums). στο Erlang shell και στη συνέχεια sums:sum( 2,3,4 ). Αναμένεται 9. Κάθε…

Erlang — αναδρομή και αντιστοίχιση προτύπων

Δημιούργησε πραγματικό module

-module(sums).
-export([sum/1]).
sum([]) -> 0;
sum([Head | Tail]) when is_integer(Head) ->
    Head + sum(Tail).

Αποθήκευσε ως sums.erl, κάλεσε c(sums). στο Erlang shell και στη συνέχεια sums:sum([2,3,4]). Αναμένεται 9. Κάθε βήμα απομακρύνει ένα στοιχείο της λίστας και η κενή λίστα τερματίζει την αναδρομή. Το guard απαιτεί ακέραιο, χωρίς αυτόματη μετατροπή κειμένου.

Αναπαραγωγή αποτυχίας

Κάλεσε sums:sum([2,apple]). Για το atom δεν υπάρχει κατάλληλο clause. Κατάγραψε το πραγματικό exception και αποφάσισε αν το API πρέπει να απορρίπτει ή να επιστρέφει ειδικό αποτέλεσμα λάθους. Μην αγνοείς άκυρα στοιχεία.

Πείραμα με διεργασία

Όρισε Receiver = self() και χρησιμοποίησε spawn(fun() -> Receiver ! sums:sum([1,2,3]) end). Παραλαβή με receive δείχνει τη μεταφορά μηνύματος. Εξήγησε τη διαφορά με κοινή μεταβλητή και σημείωσε OTP έκδοση και αποτελέσματα. Δεν έχει εκτελεστεί εδώ.

Πρόσθεσε ρητό αποτέλεσμα σφάλματος

Μια πραγματική συνάρτηση μπορεί να επιστρέφει {ok, Total} για έγκυρη λίστα και {error, bad_item} όταν ένα στοιχείο παραβιάζει το guard. Σύγκρινε προέλεγχο όλης της λίστας με πρόσθετο clause που επιστρέφει το πρώτο άκυρο στοιχείο. Χρησιμοποίησε [1,2], [], [1,apple] και [1,2.5]. Η Erlang διαχωρίζει ακέραιους από κινητής υποδιαστολής: το 2.5 απορρίπτεται από is_integer. Στο πείραμα με διεργασίες πρόσθεσε αναγνωριστικό αίτησης στο μήνυμα και receive ... after με όριο αναμονής. Εξήγησε πώς διαχειρίζεσαι διεργασία που αποτυγχάνει πριν απαντήσει, αντί να περιμένεις για πάντα.

Erlang

Η ανταλλαγή μηνυμάτων δεν είναι κοινή μνήμη

Στην Erlang οι processes είναι ελαφριές οντότητες με ξεχωριστά mailboxes. Η send expression στέλνει μήνυμα αλλά δεν περιμένει ότι ο receiver το επεξεργάστηκε. Αυτή η διάκριση είναι κρίσιμη όταν σχεδιάζεις request/response πρωτόκολλο.

-module(echo_demo).
-export([start/0, loop/0]).

loop() ->
    receive
        {From, Ref, Value} ->
            From ! {Ref, Value},
            loop();
        stop ->
            ok
    end.

start() ->
    Pid = spawn(?MODULE, loop, []),
    Ref = make_ref(),
    Pid ! {self(), Ref, hello},
    Result = receive
        {Ref, Answer} -> Answer
    after 1000 ->
        timeout
    end,
    Pid ! stop,
    Result.

Αφού μεταγλωττίσεις το module και καλέσεις echo_demo:start()., το κανονικό αποτέλεσμα αναμένεται να είναι hello. Η μοναδική Ref βοηθά στην αντιστοίχιση της απάντησης με το συγκεκριμένο request και αποτρέπει λανθασμένη κατανάλωση άσχετης απάντησης όταν υπάρχουν πολλαπλές κλήσεις.

Τι αποδεικνύει το timeout

Αν το receive τελειώσει με timeout, αυτό δεν αποδεικνύει ότι το μήνυμα χάθηκε: μπορεί να καθυστέρησε ο scheduler ή να βρίσκεται στο mailbox. Ο sender δεν γνωρίζει από μόνος του αν ο receiver επεξεργάστηκε, απέτυχε ή τερμάτισε. Για πιο αξιόπιστο lifecycle εξέτασε process monitors και πότε ταιριάζει OTP gen_server αντί ιδιοκατασκευής πρωτοκόλλου.

Μηνύματα σε σειρά

Τα μηνύματα από τον ίδιο sender στον ίδιο receiver διατηρούν τη σειρά αποστολής, αλλά μην συμπεραίνεις συνολική σειρά όταν πολλοί senders γράφουν στο ίδιο mailbox. Ο receiver έχει δική του σειρά εξυπηρέτησης και selective receive μπορεί να παρακάμψει παλαιότερα μηνύματα που δεν ταιριάζουν στο pattern.

Πρόκληση

Πρόσθεσε δεύτερο request με διαφορετική Ref και σύγκρινε αποτελέσματα. Μετά βάλε τεχνητή καθυστέρηση στη worker ώστε να ενεργοποιηθεί το after clause. Έλεγξε τι συμβαίνει σε late replies. Κατάγραψε OTP/Erlang έκδοση, πραγματικά outputs, και σημείωσε πώς ο caller προστατεύει το mailbox από απαντήσεις που δεν περιμένει πλέον.

Erlang — Παραδείγματα πραγματικού κώδικα

Εκτέλεση των παραδειγμάτων

Τα παραδείγματα είναι μικρά και αυτοτελή. Χρησιμοποίησε τη σχετική εγκατεστημένη γλώσσα. Ενδεικτικά: escript {file}. Μη συγχέεις τα ονόματα αρχείων με αυτόματη εγκατάσταση. Δούλεψε σε δοκιμαστικό φάκελο.

Erlang — Τεχνικά σημεία και συχνές παγίδες

Τεχνική γνώση

  1. Οι διεργασίες επικοινωνούν με μηνύματα αντί για κοινό μεταβαλλόμενο heap όπως στα νήματα.
  2. Το pattern matching χρησιμοποιείται σε συναρτήσεις και μηνύματα.
  3. Οι δομές OTP και supervision υποστηρίζουν υπηρεσίες ανθεκτικές σε αστοχίες.