kpr% talk levy@toul ... kpr% netstat -a Active Internet connections (including servers) tcp 0 0 kpriss.inria.fr.1042 toul.inria.fr.1026 ESTABLISHED udp 0 0 kpriss.inria.fr.1416 *.* tou% talk levy@kpriss tou% netstat -a Active Internet connections (including servers) Proto Recv-Q Send-Q Local Address Foreign Address (state) tcp 0 0 toul.inria.fr.1026 kpriss.inria.fr.1042 ESTABLISHED udp 0 0 toul.inria.fr.1143 *.*
main(argc, argv) int argc; char *argv[]; { get_names(argc, argv); init_display(); open_ctl(); open_sockt(); start_msgs(); if (!check_local() ) invite_remote(); end_msgs(); set_edit_chars(); talk(); } get_addrs(my_machine_name, his_machine_name) char *my_machine_name, *his_machine_name; { ... /* find the server's port */ sp = getservbyname("ntalk", "udp"); if (sp == 0) { fprintf(stderr, "talk: %s/%s: service is not registered.\n", "ntalk", "udp"); exit(-1); } daemon_port = sp->s_port; } u_short daemon_port; /* port number of the talk daemon */ int ctl_sockt; int sockt; int invitation_waiting = 0; CTL_MSG msg;
/* open the ctl socket */ open_ctl() { int length; ctl_addr.sin_port = 0; ctl_addr.sin_addr = my_machine_addr; ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0); if (ctl_sockt <= 0) p_error("Bad socket"); if (bind(ctl_sockt, &ctl_addr, sizeof(ctl_addr), 0) != 0) p_error("Couldn't bind to control socket"); length = sizeof(ctl_addr); if (getsockname(ctl_sockt, &ctl_addr, &length) == -1) p_error("Bad address for ctl socket"); } open_sockt() { int length; my_addr.sin_addr = my_machine_addr; my_addr.sin_port = 0; sockt = socket(AF_INET, SOCK_STREAM, 0); if (sockt <= 0) p_error("Bad socket"); if (bind(sockt, &my_addr, sizeof(my_addr)) != 0) p_error("Binding local socket"); length = sizeof(my_addr); if (getsockname(sockt, &my_addr, &length) == -1) p_error("Bad address for socket"); } invite_remote() { ... announce_invite(); setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); message("Waiting for your party to respond"); signal(SIGALRM, re_invite); (void) setjmp(invitebuf); while ((new_sockt = accept(sockt, 0, 0)) < 0) { if (errno == EINTR) continue; p_error("Unable to connect with your partÿ); } close(sockt); sockt = new_sockt; current_state = "Waiting for your party to respond"; start_msgs(); ... } announce_invite() { CTL_RESPONSE response; current_state = "Trying to connect to your party's talk daemon"; ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); remote_id = response.id_num; if (response.answer != SUCCESS) { if (response.answer < NANSWERS) message(answers[response.answer]); quit(); } /* leave the actual invitation on my talk daemon */ ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); local_id = response.id_num; } /* * SOCKDGRAM is unreliable, so we must repeat messages if we have * not recieved an acknowledgement within a reasonable amount * of time */ ctl_transact(target, msg, type, rp) struct in_addr target; CTL_MSG msg; int type; CTL_RESPONSE *rp; { int read_mask, ctl_mask, nready, cc; struct timeval wait; msg.type = type; daemon_addr.sin_addr = target; daemon_addr.sin_port = daemon_port; ctl_mask = 1 << ctl_sockt; /* * Keep sending the message until a response of * the proper type is obtained. */ do { wait.tv_sec = CTL_WAIT; wait.tv_usec = 0; /* resend message until a response is obtained */ do { cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0, &daemon_addr, sizeof (daemon_addr)); if (cc != sizeof (msg)) { if (errno == EINTR) continue; p_error("Error on write to talk daemon"); } read_mask = ctl_mask; nready = select(32, &read_mask, 0, 0, &wait); if (nready < 0) { if (errno == EINTR) continue; p_error("Error waiting for daemon responsë); } } while (nready == 0); /* * Keep reading while there are queued messages * (this is not necessary, it just saves extra * request/acknowledgements being sent) */ do { cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0); if (cc < 0) { if (errno == EINTR) continue; p_error("Error on read from talk daemon"); } read_mask = ctl_mask; /* an immediate poll */ timerclear(&wait); nready = select(32, &read_mask, 0, 0, &wait); } while (nready > 0 && (rp->vers != TALK_VERSION || rp->type != type)); } while (rp->vers != TALK_VERSION || rp->type != type); rp->id_num = ntohl(rp->id_num); rp->addr.sa_family = ntohs(rp->addr.sa_family); }
/* talkd */ main(argc, argv) int argc; char *argv[]; { struct sockaddr_in from; int fromlen, cc; if (getuid()) { fprintf(stderr, "Talkd : not super user\n"); exit(1); } (void) gethostname(hostname, sizeof (hostname)); (void) chdir("/dev"); (void) signal(SIGALRM, timeout); (void) alarm(TIMEOUT); for (;;) { extern int errno; fromlen = sizeof(from); cc = recvfrom(0, (char *)&request, sizeof (request), 0, &from, &fromlen); if (cc != sizeof(request)) { if (cc < 0 && errno != EINTR) perror("recvfrom"); continue; } lastmsgtime = time(0); swapmsg(&request); if (debug) print_request(&request); process_request(&request, &response); /* can block here, is this what I want? */ cc = sendto(0, (char *) &response, sizeof (response), 0, &request.ctl_addr, sizeof (request.ctl_addr)); if (cc != sizeof(response)) perror("sendto"); } }
/etc/services
et lance le serveur correspondant.
echo 7/tcp echo 7/udp daytime 13/tcp daytime 13/udp ftp 21/tcp telnet 23/tcp smtp 25/tcp mail time 37/tcp timserver time 37/udp timserver finger 79/tcp login 513/tcp who 513/udp whod dictionary 10300/tcp webster
setsockopt()
et getsockopt()
. Exemples: SO_KEEPALIVE
,
SO_LINGER
.
htonl
, htons
, ntohl
, ntohl
convertissent
les entiers cours ou longs entre les machines hotes et la convention
réseau (grand endian), puisqu'il faut bien un standard de
communication entre des machines d'endianité différente.
pauillac.inria.fr
. Il y a le domaine fr
, puis le
sous-domaine inria
, etc.
/etc/hosts
ou par gethostbyname()
. Mais si l'adresse est
très lointaine on la retrouve par un serveur de noms (DNS ou Domain
Name Server et BIND).
nslookup
est une commande qui permet d'avoir des
informations en intéractif. Par exemple, les serveurs connaissant
l'INRIA.
% nslookup Default Server: concorde.inria.fr Address: 192.93.2.39 > set type=any > inria.fr Server: concorde.inria.fr Address: 192.93.2.39 inria.fr origin = ns1.nic.fr mail addr = hostmaster.inria.fr serial=96031908, refresh=21600, retry=3600, expire=3600000, min=172800 inria.fr nameserver = ns1.nic.fr inria.fr nameserver = ns2.nic.fr inria.fr nameserver = mirsa.inria.fr inria.fr nameserver = imag.imag.fr inria.fr nameserver = ns.eu.net inria.fr nameserver = princeton.edu
traceroute
donne le chemin emprunté. Exemple:
% /usr/sbin/traceroute poly.polytechnique.fr traceroute to poly.polytechnique.fr (129.104.252.1), 30 hops max, 40 byte packets 1 rocq-gwf.inria.fr (128.93.1.100) 4 ms 3 ms 4 ms 2 rocq-gwr.inria.fr (192.93.1.92) 3 ms 4 ms 5 ms 3 inria-rocquencourt.rerif.ft.net (192.93.122.1) 4 ms 4 ms 4 ms 4 boulogne.rerif.ft.net (193.48.55.57) 6 ms 7 ms 7 ms 5 stlamb12.rerif.ft.net (193.48.53.41) 10 ms 10 ms 12 ms 6 stlamb1.rerif.ft.net (193.48.53.161) 11 ms 11 ms 14 ms 7 stlamb3.rerif.ft.net (193.48.53.11) 11 ms 11 ms 11 ms 8 massy1.rerif.ft.net (193.48.53.18) 11 ms 12 ms 11 ms 9 ep-palaiseau.rerif.ft.net (193.48.54.26) 17 ms 15 ms 15 ms 10 192.70.27.13 (192.70.27.13) 17 ms 14 ms 16 ms 11 192.70.27.13 (192.70.27.13) 17 ms !H 17 ms !H *
TIT .Le routage dans l'Internet SLA .Christian Huitema; Eyrolles, 1995
On a des processus fiables et non fiables. On veut que:
TIT .Parallel program design : a foundation SLA .K. Mani Chandy, Jayadev Misra. - Reading, MA US ; Don Mills, .Ontario ; Wokingham, England : Addison-Wesley, 1988. - .XXVIII-516 p. ; 24 cm. TIT .Handbook of Theoretical Computer Science. MIT Press, ed. van Leewen, 1990. Chapter 18, Leslie Lamport, Nancy Lynch, pp 1159-1199.
Enoncé (bis): Quelques généraux félons se sont mêlés à l'armée byzantine qui doit néanmoins avancer en ordre. Il faut donc que:
Leslie Lamport, Rob Shostak, Marshall Pease The Byzantine Generals Problem ACM/TOPLASS, Vol 4, N 3, Jul 1982 Danny Dolev The Byzantine Generals Strike Again The Journal of Algorithms,1982On peut montrer qu'il n'existe de solution que si le nombre de généraux n est plus grand que 3 m + 1 où m est le nombre de traîtres.
Lamport, Shostak, Pease -- Dolev
)
OM(m) si m = 0
RETRAITE
. Le général i fait
comme le général en chef en lancant la valeur recue avec OM(m-1) pour les n-2 autres
lieutenants, RETRAITE
si
rien reçu). Le général i fait un vote à majorité sur l'ensemble
{v_1, v_2, ... v_n-1}.
Exercice: Faire l'exemple avec 4 généraux (les 2 cas où le chef ou un lieutenant est traître). Prouver la correction de l'algorithme.