Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (58)
Showing
with 620 additions and 0 deletions
stages:
- triggers
trigger_exo01:
stage: triggers
trigger:
include: 01-emetteurUDPv4/.gitlab-ci.yml
rules:
- changes:
- 01-emetteurUDPv4/*.c
trigger_exo02:
stage: triggers
trigger:
include: 02-config-adresse/.gitlab-ci.yml
rules:
- changes:
- 02-config-adresse/*.c
trigger_exo03:
stage: triggers
trigger:
include: 03-recepteurUDPv4/.gitlab-ci.yml
rules:
- changes:
- 03-recepteurUDPv4/*.c
trigger_exo04:
stage: triggers
trigger:
include: 04-affichage-adresse/.gitlab-ci.yml
rules:
- changes:
- 04-affichage-adresse/*.c
trigger_exo05:
stage: triggers
trigger:
include: 05-emetteurUDPv6/.gitlab-ci.yml
rules:
- changes:
- 05-emetteurUDPv6/*.c
trigger_exo06:
stage: triggers
trigger:
include: 06-recepteurUDPv6/.gitlab-ci.yml
rules:
- changes:
- 06-recepteurUDPv6/*.c
trigger_exo07:
stage: triggers
trigger:
include: 07-emetteurTCPv4/.gitlab-ci.yml
rules:
- changes:
- 07-emetteurTCPv4/*.c
trigger_exo08:
stage: triggers
trigger:
include: 08-recepteurTCPv4/.gitlab-ci.yml
rules:
- changes:
- 08-recepteurTCPv4/*.c
trigger_exo09:
stage: triggers
trigger:
include: 09-transfert-fichierTCPv6-source/.gitlab-ci.yml
rules:
- changes:
- 09-transfert-fichierTCPv6-source/*.c
trigger_exo10:
stage: triggers
trigger:
include: 10-transfert-fichierTCPv6-dest/.gitlab-ci.yml
rules:
- changes:
- 10-transfert-fichierTCPv6-dest/*.c
trigger_exo11:
stage: triggers
trigger:
include: 11-dialogue-serveurTCP/.gitlab-ci.yml
rules:
- changes:
- 11-dialogue-serveurTCP/*.c
trigger_exo12:
stage: triggers
trigger:
include: 12-chat/.gitlab-ci.yml
rules:
- changes:
- 12-chat/*.c
stages:
- build
- test
image: montavont/algodesreseaux
build_01:
stage: build
script:
- cd 01-emetteurUDPv4
- scons
artifacts:
paths:
- 01-emetteurUDPv4/sender-udp
# run tests using the binary build before
test_01:
stage: test
needs: [build_01]
script:
- |
echo "starting test"
cd 01-emetteurUDPv4
bash tests.sh
File added
# Algorithmes des réseaux
## Expéditeur UDP IPv4
Complétez le programme `sender-udp.c` pour envoyer le message texte `hello world` avec les protocoles `IPv4` et `UDP`.
Le programme admet en argument le numéro de port de l'hôte distant à contacter :
./sender-udp port_number
Les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
**Objectifs :** savoir créer un socket et transmettre un message texte en UDP.
## Marche à suivre
Vous devez dans un premier temps créer un socket `IPv4` et `UDP` via la primitive :
int socket (int domain, int type, int protocol)
Ensuite, vous devez renseigner l'adresse `IPv4` et le port du destinataire dans une variable de type `struct sockaddr_in` définie dans `<netinet/in.h>` :
struct sockaddr_in {
short sin_family; // famille
unsigned short sin_port; // port au format réseau
struct in_addr sin_addr; // cf. struct in_addr ci-dessous
char sin_zero[8];
};
struct in_addr {
unsigned long s_addr; // adresse IPv4 au format réseau
};
Néanmoins, afin d'écrire des programmes les plus indépendants possibles des familles des sockets, il faut utiliser une variable de type `struct sockaddr_storage` et ensuite caster cette dernière suivant la famille traitée :
struct sockaddr_storage ss;
struct sockaddr_in *in = (struct sockaddr_in *) &ss;
L'adresse IPv4 du destinataire est déjà renseignée au bon format par la constante `IP` dans les sources du programme et peut être simplement affectée au champ correspondant dans la structure d'adresse.
Vous devez convertir le numéro de port passé en argument du programme en entier puis utiliser la macro `PORT()` disponible dans les sources du programme lors de son utilisation pour compléter une structure d'adresse. Vous pouvez laisser le système d'exploitation choisir l'adresse `IPv4` et le port utilisés localement par votre programme pour émettre le message.
Enfin, l'envoi du message se fait via la primitive :
ssize_t sendto (int socket, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len)
Vous pouvez tester votre programme en exécutant la commande `nc` (netcat) dans un autre terminal afin d'écouter en `UDP` sur l'adresse `127.0.0.1` et le port de votre choix :
nc -4ul 127.0.0.1 port_number
Vous pouvez ensuite lancer votre programme dans un autre terminal et vérifier que le message transmis est bien affiché par `netcat` sur la sortie standard.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#define CHECK(op) do { if ( (op) == -1) { perror (#op); exit (EXIT_FAILURE); } \
} while (0)
#define IP 0x100007f /* 127.0.0.1 */
#define PORT(p) htons(p)
void raler(char * chaine){
fprintf(stderr,"%s\n",chaine);
exit(EXIT_FAILURE);
}
int main (int argc, char *argv [])
{
/* test arg number */
if(argc!= 2){
raler("Wrong arguments number\n");
}
/* convert and check port number */
int port_number = atoi(argv[1]);
if(port_number < 10000 || port_number > 65000){
raler("Wrong port value : port_number not in [10000;65000]");
}
/* create socket */
int new_socket;
CHECK(new_socket=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP));
/* complete sockaddr struct */
struct sockaddr_storage storage;
struct sockaddr_in *pointer=(struct sockaddr_in *)&storage;
pointer->sin_port=PORT(port_number);
pointer->sin_addr.s_addr=IP;
pointer->sin_family=AF_INET;
/* send message to remote peer */
int bytes_sent = sendto(new_socket,"hello world\0",12,0,(struct sockaddr*)pointer,sizeof(struct sockaddr_in));
CHECK(bytes_sent);
/* close socket */
close(new_socket);
return 0;
}
#!/bin/bash
PROG="./sender-udp"
PORT=`shuf -i 10000-65000 -n 1`
echo -n "test 01 - program without arg: "
$PROG > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 02 - invalid port number: "
$PROG 65001 > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 03 - program exits without error: "
timeout 5 nc -4ul 127.0.0.1 $PORT > output &
sleep 2
! $PROG $PORT 2> /dev/null && echo "KO -> exit status != 0" && exit 1
echo "...OK"
echo -n "test 04 - program sends a message: "
MES=`cat output`
[ -z "$MES" ] && echo "KO -> no message" && exit 1
echo ".......OK"
echo -n "test 05 - message is valid: "
[ "$MES" != "hello world" ] && echo "KO - received: $MES | expected: hello world" && exit 1
echo "..............OK"
echo -n "test 06 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
valgrind --leak-check=full --error-exitcode=100 --log-file=valgrind.log $PROG $PORT
[ "$?" == "100" ] && echo "KO -> memory pb please check valgrind.log" && exit 1
echo "..................OK"
rm output valgrind.log
stages:
- build
- test
image: montavont/algodesreseaux
build_02:
stage: build
script:
- cd 02-config-adresse
- scons
artifacts:
paths:
- 02-config-adresse/sender-udp
# run tests using the binary build before
test_02:
stage: test
needs: [build_02]
script:
- |
echo "starting test"
cd 02-config-adresse
bash tests.sh
File added
# Algorithmes des réseaux
## Configuration adresse et port
Dans le programme précédent, l'adresse IP et le port du destinataire étaient fixes et fournis au bon format directement dans le code source. Dans cet exercice, vous allez laissez le système compléter la structure `struct sockaddr_storage` à partir d'une adresse IP et d'un port sous la forme de chaînes de caractères.
L'objectif reste le même que pour l'exercice précédent : complétez le programme `sender-udp.c` pour envoyer le message texte `hello world` avec les protocoles `IPv4` et `UDP`.
On rappelle que les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
**Objectifs :** savoir renseigner une structure d'adresse à l'aide de la fonction `getaddrinfo()`
## Marche à suivre
Après avoir créer un socket (via la primitive `socket`), vous pouvez appeler la fonction :
int getaddrinfo (const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
sur l'adresse `127.0.0.1` et le port passé en argument du programme, tout deux exprimés sous la forme de chaînes de caractères, afin de récupérer une liste de structure `struct addrinfo` :
struct addrinfo {
int ai_flags; /* options supplémentaires */
int ai_family; /* famille */
int ai_socktype; /* type */
int ai_protocol; /* protocole */
size_t ai_addrlen; /* longueur de struct sockaddr */
struct sockaddr *ai_addr; /* adresse et port */
char *ai_canonname; /* nom de l'hôte */
struct addrinfo *ai_next; /* pointeur sur l'élément suivant */
};
Ce type est défini dans `<netdb.h>`.
En cas de succès, le pointeur `res` pointe sur une liste de `struct addrinfo` terminée par `NULL` car un hôte peut posséder plusieurs adresses IP ou avoir plusieurs services (port) actifs :
![list of struct addrinfo](addrinfo.svg)
À l'aide du paramètre `hints` vous pouvez filtrer les résultats obtenus dans la liste. Consultez le manuel utilisateur pour connaître les options possibles et comment traiter les erreurs associées à la fonction `getaddrinfo()`.
En cas de succès, vous pouvez directement utiliser les informations présentes dans la structure `struct addrinfo` lors de l'appel à la fonction `sendto()`.
La fonction `getaddrinfo()` alloue dynamiquement la mémoire nécessaire pour stocker la liste de structures `struct addrinfo`. Il faut donc libérer cette dernière lorsque la liste n'est plus utile via la fonction :
void freeaddrinfo (struct addrinfo *ai)
Vous pouvez tester votre programme en exécutant la commande `nc` (netcat) dans un autre terminal afin d'écouter en `UDP` sur l'adresse `127.0.0.1` et le port de votre choix :
nc -4ul 127.0.0.1 port_number
Vous pouvez ensuite lancer votre programme dans un autre terminal et vérifier que le message transmis est bien affiché par `netcat` sur la sortie standard.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file with editors other than draw.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="656px" height="211px" viewBox="-0.5 -0.5 656 211" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2023-06-08T11:37:49.570Z&quot; agent=&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15&quot; etag=&quot;6-i2Dn6O12TiGqKzJkI4&quot; version=&quot;21.3.7&quot;&gt;&#10; &lt;diagram name=&quot;Page-1&quot; id=&quot;iaEp2pig46ds9_IwXVr7&quot;&gt;&#10; &lt;mxGraphModel dx=&quot;2074&quot; dy=&quot;1187&quot; grid=&quot;1&quot; gridSize=&quot;10&quot; guides=&quot;1&quot; tooltips=&quot;1&quot; connect=&quot;1&quot; arrows=&quot;1&quot; fold=&quot;1&quot; page=&quot;1&quot; pageScale=&quot;1&quot; pageWidth=&quot;827&quot; pageHeight=&quot;1169&quot; math=&quot;0&quot; shadow=&quot;0&quot;&gt;&#10; &lt;root&gt;&#10; &lt;mxCell id=&quot;0&quot; /&gt;&#10; &lt;mxCell id=&quot;1&quot; parent=&quot;0&quot; /&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-3&quot; value=&quot;struct addrinfo *list;&amp;lt;br&amp;gt;getaddrinfo (&amp;quot;google.com&amp;quot;, &amp;quot;80&amp;quot;, NULL, &amp;amp;amp;list);&quot; style=&quot;text;html=1;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;whiteSpace=wrap;rounded=0;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;30&quot; y=&quot;60&quot; width=&quot;320&quot; height=&quot;30&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-4&quot; value=&quot;&amp;amp;nbsp;struct addrinfo {&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;&amp;lt;/span&amp;gt;...&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;struct sockaddr *ai_addr;&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;...&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;struct addrinfo *ai_next;&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;...&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;amp;nbsp;}&amp;amp;nbsp;&quot; style=&quot;rounded=0;whiteSpace=wrap;html=1;align=left;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;30&quot; y=&quot;150&quot; width=&quot;200&quot; height=&quot;120&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-5&quot; value=&quot;&amp;amp;nbsp;struct addrinfo {&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;&amp;lt;/span&amp;gt;...&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;struct sockaddr *ai_addr;&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;...&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;struct addrinfo *ai_next;&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;white-space: pre;&amp;quot;&amp;gt;&amp;#x9;...&amp;lt;br&amp;gt;&amp;lt;/span&amp;gt;&amp;amp;nbsp;}&amp;amp;nbsp;&quot; style=&quot;rounded=0;whiteSpace=wrap;html=1;align=left;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;280&quot; y=&quot;150&quot; width=&quot;200&quot; height=&quot;120&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-10&quot; value=&quot;&quot; style=&quot;endArrow=none;html=1;rounded=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;190&quot; y=&quot;225&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;260&quot; y=&quot;225&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-11&quot; value=&quot;&quot; style=&quot;endArrow=none;html=1;rounded=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;260&quot; y=&quot;225&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;260&quot; y=&quot;120&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-12&quot; value=&quot;&quot; style=&quot;endArrow=none;html=1;rounded=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;260&quot; y=&quot;120&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;380&quot; y=&quot;120&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-13&quot; value=&quot;&quot; style=&quot;endArrow=classic;html=1;rounded=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;379.5&quot; y=&quot;120&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;380&quot; y=&quot;150&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-14&quot; value=&quot;&quot; style=&quot;endArrow=classic;html=1;rounded=0;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;129.5&quot; y=&quot;119&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;129.5&quot; y=&quot;149&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-15&quot; value=&quot;list&quot; style=&quot;text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;100&quot; y=&quot;94&quot; width=&quot;60&quot; height=&quot;30&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-16&quot; value=&quot;&quot; style=&quot;endArrow=classic;html=1;rounded=0;endFill=1;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;444&quot; y=&quot;225&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;514&quot; y=&quot;225&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-20&quot; value=&quot;...&quot; style=&quot;text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;506&quot; y=&quot;207&quot; width=&quot;60&quot; height=&quot;30&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-21&quot; value=&quot;&quot; style=&quot;endArrow=classic;html=1;rounded=0;endFill=1;&quot; edge=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry width=&quot;50&quot; height=&quot;50&quot; relative=&quot;1&quot; as=&quot;geometry&quot;&gt;&#10; &lt;mxPoint x=&quot;554&quot; y=&quot;225&quot; as=&quot;sourcePoint&quot; /&gt;&#10; &lt;mxPoint x=&quot;624&quot; y=&quot;225&quot; as=&quot;targetPoint&quot; /&gt;&#10; &lt;/mxGeometry&gt;&#10; &lt;/mxCell&gt;&#10; &lt;mxCell id=&quot;du7DQQFkr--0zr6OPIsH-22&quot; value=&quot;NULL&quot; style=&quot;text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;&quot; vertex=&quot;1&quot; parent=&quot;1&quot;&gt;&#10; &lt;mxGeometry x=&quot;625&quot; y=&quot;211&quot; width=&quot;60&quot; height=&quot;30&quot; as=&quot;geometry&quot; /&gt;&#10; &lt;/mxCell&gt;&#10; &lt;/root&gt;&#10; &lt;/mxGraphModel&gt;&#10; &lt;/diagram&gt;&#10;&lt;/mxfile&gt;&#10;" resource="https://app.diagrams.net/"><defs/><g><rect x="0" y="0" width="320" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 318px; height: 1px; padding-top: 15px; margin-left: 2px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">struct addrinfo *list;<br />getaddrinfo ("google.com", "80", NULL, &amp;list);</div></div></div></foreignObject><text x="2" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">struct addrinfo *list;...</text></switch></g><rect x="0" y="90" width="200" height="120" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 198px; height: 1px; padding-top: 150px; margin-left: 2px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> struct addrinfo {<br /><span style="white-space: pre;"> </span>...<br /><span style="white-space: pre;"> struct sockaddr *ai_addr;<br /></span><span style="white-space: pre;"> ...<br /></span><span style="white-space: pre;"> struct addrinfo *ai_next;<br /></span><span style="white-space: pre;"> ...<br /></span> } </div></div></div></foreignObject><text x="2" y="154" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">struct addrinfo {...</text></switch></g><rect x="250" y="90" width="200" height="120" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 198px; height: 1px; padding-top: 150px; margin-left: 252px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"> struct addrinfo {<br /><span style="white-space: pre;"> </span>...<br /><span style="white-space: pre;"> struct sockaddr *ai_addr;<br /></span><span style="white-space: pre;"> ...<br /></span><span style="white-space: pre;"> struct addrinfo *ai_next;<br /></span><span style="white-space: pre;"> ...<br /></span> } </div></div></div></foreignObject><text x="252" y="154" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px">struct addrinfo {...</text></switch></g><path d="M 160 165 L 230 165" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 230 165 L 230 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 230 60 L 350 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 349.5 60 L 349.89 83.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 349.98 88.88 L 346.37 81.94 L 349.89 83.63 L 353.36 81.82 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 99.5 59 L 99.5 82.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 99.5 87.88 L 96 80.88 L 99.5 82.63 L 103 80.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="70" y="34" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 49px; margin-left: 71px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">list</div></div></div></foreignObject><text x="100" y="53" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">list</text></switch></g><path d="M 414 165 L 477.63 165" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 482.88 165 L 475.88 168.5 L 477.63 165 L 475.88 161.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="476" y="147" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 162px; margin-left: 477px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">...</div></div></div></foreignObject><text x="506" y="166" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">...</text></switch></g><path d="M 524 165 L 587.63 165" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 592.88 165 L 585.88 168.5 L 587.63 165 L 585.88 161.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="595" y="151" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 166px; margin-left: 596px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">NULL</div></div></div></foreignObject><text x="625" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">NULL</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <netdb.h>
#define CHECK(op) do { if ((op) == -1) { perror(#op); exit(EXIT_FAILURE); } } while (0)
#define IP "127.0.0.1"
#define PORT(p) htons(p)
void raler(const char *chaine) {
fprintf(stderr, "%s\n", chaine);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[]) {
const char *msg = "hello world\n";
/* test arg number */
if (argc != 2) {
raler("argc\n");
}
/* convert and check port number */
int port_number = atoi(argv[1]);
if (port_number < 10000 || port_number > 65000) {
raler("Wrong port value: port_number not in [10000;65000]");
}
/* create socket */
int new_socket;
CHECK(new_socket = socket(AF_INET, SOCK_DGRAM, 0)); // 0 for protocol
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // Use IPv4
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(IP, argv[1], &hints, &res) != 0) {
raler("getaddrinfo\n");
}
/* send message to remote peer */
int bytes_sent = sendto(new_socket, msg, strlen(msg), 0, res->ai_addr, res->ai_addrlen);
CHECK(bytes_sent);
/* close socket */
close(new_socket);
freeaddrinfo(res); // Free the dynamically allocated address info
return 0;
}
#!/bin/bash
PROG="./sender-udp"
PORT=`shuf -i 10000-65000 -n 1`
echo -n "test 01 - program without arg: "
$PROG > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 02 - invalid port number: "
$PROG 65001 > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 03 - program exits without error: "
timeout 5 nc -4ul 127.0.0.1 $PORT > output &
sleep 2
! $PROG $PORT 2> /dev/null && echo "KO -> exit status != 0" && exit 1
echo "...OK"
echo -n "test 04 - program sends a message: "
MES=`cat output`
[ -z "$MES" ] && echo "KO -> no message" && exit 1
echo ".......OK"
echo -n "test 05 - message is valid: "
[ "$MES" != "hello world" ] && echo "KO - received: $MES | expected: hello world" && exit 1
echo "..............OK"
echo -n "test 06 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
valgrind --leak-check=full --error-exitcode=100 --log-file=valgrind.log $PROG $PORT
[ "$?" == "100" ] && echo "KO -> memory pb please check valgrind.log" && exit 1
echo "..................OK"
rm output valgrind.log
stages:
- build
- test
image: montavont/algodesreseaux
build_03:
stage: build
script:
- cd 03-recepteurUDPv4
- scons
artifacts:
paths:
- 03-recepteurUDPv4/receiver-udp
# run tests using the binary build before
test_03:
stage: test
needs: [build_03]
script:
- |
echo "starting tests"
cd 03-recepteurUDPv4
bash tests.sh
File added
# Algorithmes des réseaux
## Récepteur UDP IPv4
Complétez le programme `receiver-udp.c` pour recevoir un message texte avec les protocoles `IPv4` et `UDP` et l'afficher sur la sortie standard.
Le programme admet en argument le numéro de port sur lequel le programme doit écouter :
./receiver-udp port_number
Les seuls numéros de port valides sont ceux contenus dans l'intervalle `[10000; 65000]`.
On fera l'hypothèse que le message aura une taille maximum de `SIZE` caractères avec `SIZE < 100`.
**Objectifs :** savoir recevoir un message texte en UDP.
## Marche à suivre
Vous devez créer un socket `IPv4` et `UDP` puis renseigner un structure d'adresse avec l'adresse `127.0.0.1` et le port passé en argument du programme à l'aide de la fonction `getaddrinfo()` introduite dans l'exercice précédent.
Il faut ensuite associer le socket avec votre l'adresse et le port via la primitive :
int bind (int socket, const struct sockaddr *address, socklen_t address_len)
L'idée ici consiste à directement utiliser les informations présentes dans la structure `struct addrinfo` retournée par `getaddrinfo()` pour les lier au socket.
Enfin, la réception d'un message se fait via la primitive :
ssize_t recvfrom (int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address,
socklen_t *restrict address_len)
Vous pouvez utiliser le pointeur `NULL` pour les deux derniers arguments de cette primitive.
Vous pouvez tester votre programme avec le programme réalisé dans l'exercice 2 ou en exécutant la commande `nc` (netcat) dans un autre terminal. Lancez votre programme dans un terminal puis exécutez la commande suivante dans un second terminal afin d'envoyer le message `hello world` en `UDP` sur l'adresse `127.0.0.1` et le port utilisé par votre programme :
echo "hello world" | nc -4u -w1 127.0.0.1 port_number
Vérifiez ensuite que le message est correctement reçu et affiché par votre programme sur la sortie standard.
## Validation
Votre programme doit obligatoirement passer tous les tests sur gitlab (il suffit de `commit/push` le fichier source pour déclencher le pipeline de compilation et de tests) avant de passer à l'exercice suivant.
sources = Glob ("*.c")
CFLAGS = ["-Wall", "-Wextra", "-Werror", "-g"]
env = Environment (CCFLAGS = CFLAGS)
env.Program (sources)
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#define CHECK(op) do { if ( (op) == -1) { perror (#op); exit (EXIT_FAILURE); } \
} while (0)
#define IP "127.0.0.1"
#define SIZE 100
void raler(const char *chaine) {
fprintf(stderr, "%s\n", chaine);
exit(EXIT_FAILURE);
}
int main (int argc, char *argv [])
{
/* test arg number */
if(argc != 2){
raler("argc\n");
}
/* convert and check port number */
int port_number = atoi(argv[1]);
if (port_number < 10000 || port_number > 65000) {
raler("Wrong port value: port_number not in [10000;65000]");
}
/* create socket */
int new_socket;
CHECK(new_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
/* complete struct sockaddr */
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; // Use IPv4
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(IP, argv[1], &hints, &res) != 0) {
raler("getaddrinfo\n");
}
/* link socket to local IP and PORT */
CHECK(bind(new_socket,res->ai_addr,res->ai_addrlen));
/* wait for incoming message */
char buffer[SIZE];
ssize_t n;
CHECK(n=recvfrom(new_socket,buffer,SIZE,0,NULL,NULL));
/* close socket */
close(new_socket);
/* free memory */
freeaddrinfo(res);
/* print received message */
printf("%s",buffer);
return 0;
}
#!/bin/bash
PROG="./receiver-udp"
PORT=`shuf -i 10000-65000 -n 1`
echo -n "test 01 - program without arg: "
$PROG > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 02 - invalid port number: "
$PROG 65001 > /dev/null 2>&1 && echo "KO -> exit status $? instead of 1" && exit 1
echo "...........OK"
echo -n "test 03 - program exits without error: "
timeout 5 $PROG $PORT > output 2> /dev/null &
TO=$!
sleep 2
echo "hello world" | nc -4u -w1 127.0.0.1 $PORT
wait $TO
R=$?
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "0" ] && echo "KO -> exit status $R instead of 0" && exit 1
echo "...OK"
echo -n "test 04 - program received a message: "
MES=`cat output`
[ -z "$MES" ] && echo "KO -> no message received" && exit 1
echo "....OK"
echo -n "test 05 - message is valid: "
[ "$MES" != "hello world" ] && echo "KO -> message received: $MES | expected: hello world" && exit 1
echo "..............OK"
echo -n "test 06 - check bind failure: "
timeout 5 nc -4ul 127.0.0.1 $PORT > /dev/null &
TO=$!
sleep 2
timeout 1 $PROG 2> /dev/null
R="$?"
[ "$R" == "124" ] && echo "KO -> program times out" && exit 1
[ "$R" != "1" ] && echo "KO -> exit status $R instead of 1" && exit 1
wait $TO
echo "............OK"
echo -n "test 07 - memory error: "
P=`which valgrind`
[ -z "$P" ] && echo "KO -> please install valgrind" && exit 1
valgrind --leak-check=full --error-exitcode=100 --log-file=valgrind.log $PROG $PORT > /dev/null &
V=$!
sleep 3
echo "hello world" | nc -4u -w1 127.0.0.1 $PORT
wait $V
[ "$?" == "100" ] && echo "KO -> memory pb please check valgrind.log" && exit 1
echo "..................OK"
rm output valgrind.log