exercices:debut
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
exercices:debut [10/10/2019 07:11] – [TP5] webmestre | exercices:debut [30/09/2021 10:18] (Version actuelle) – [TP4] webmestre | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | Voici les données initiales pour réaliser les TP M3101. | ||
+ | |||
+ | ====== TP1 ====== | ||
+ | |||
+ | Voici les codes fourni en TD1 : | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | * {{: | ||
+ | |||
+ | Pour la question "Mise en place des sémaphores", | ||
+ | |||
+ | <WRAP center round tip 60%> | ||
+ | Les question " | ||
+ | |||
+ | Pour visualiser une trotteuse, utilisez l' | ||
+ | </ | ||
+ | |||
+ | ====== TP2 ====== | ||
+ | |||
+ | Utilisez les entêtes : | ||
+ | |||
+ | <code python> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | |||
+ | import sys | ||
+ | import struct | ||
+ | import time | ||
+ | import datetime | ||
+ | import locale | ||
+ | </ | ||
+ | |||
+ | Exemple de switch. La commande switch n' | ||
+ | <code python> | ||
+ | def f1 (): | ||
+ | print "appel de f1" | ||
+ | |||
+ | def f2 (): | ||
+ | print "appel de f2" | ||
+ | |||
+ | var=" | ||
+ | |||
+ | monSwitch = { | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | monSwitch [var] () | ||
+ | </ | ||
+ | |||
+ | On peut passer des arguments à un programme python. | ||
+ | <code python> | ||
+ | # | ||
+ | # -*- coding: utf-8 -*- | ||
+ | import sys | ||
+ | |||
+ | def f1 (): | ||
+ | print "appel de f1" | ||
+ | |||
+ | def f2 (): | ||
+ | print "appel de f2" | ||
+ | |||
+ | monSwitch = { | ||
+ | ' | ||
+ | ' | ||
+ | } | ||
+ | |||
+ | monSwitch [sys.argv[1]] () | ||
+ | </ | ||
+ | |||
+ | L' | ||
+ | <code bash> | ||
+ | $ chmod a+x monProgrammePython.py | ||
+ | $ ./ | ||
+ | </ | ||
+ | |||
+ | Pour l' | ||
+ | Par exemple on peut vouloir découper 0x41ED en 0X4 d'un côté et 0x1ED de l' | ||
+ | |||
+ | <code python> | ||
+ | fMode = 0x41ED // <=> mode = 040755 <=> mode = 16877 | ||
+ | fType = mode >> 12 // => 4 | ||
+ | ugo = fMode & 0xFFF // => 0x1ED (héxa) = 0755 (octal) = 493 (décimal) | ||
+ | </ | ||
+ | |||
+ | Les droits " | ||
+ | De façon optionnel nous pouvons traiter les bits " | ||
+ | |||
+ | <code python> | ||
+ | ugo = 00755 | ||
+ | sst = ugo >> 9 & 7 // => 0 | ||
+ | u = ugo >> 6 & 7 // => 7 | ||
+ | g = ugo >> 3 & 7 // => 5 | ||
+ | o = ugo >> 0 & 7 // <=> o = ugo & 7 => 5 | ||
+ | </ | ||
+ | |||
+ | Voici quelques fonctions utiles | ||
+ | * str (i) => traduit un entier en une chaîne de caractère représentant une valeur décimal | ||
+ | * oct (i) => traduit un entier en une chaîne de caractère représentant une valeur octal | ||
+ | * hex (i) => traduit un entier en une chaîne de caractère représentant une valeur héxadécimal | ||
+ | |||
+ | <code python> | ||
+ | i = 0x41ED | ||
+ | s = "hex: "+hex (i)+" oct: "+oct (i)+" dec: "+str (i) | ||
+ | // => hex: 0x41ed oct: 040755 dec: 16877 | ||
+ | </ | ||
+ | <WRAP center round important 60%> | ||
+ | Il y a une erreur dans le support de cours page 49 (listing 35). | ||
+ | |||
+ | <code bash> | ||
+ | $ ./ | ||
+ | 00775 | ||
+ | 07775 | ||
+ | 00664 | ||
+ | 07664 | ||
+ | 0x41ed => drwxr-xr-x | ||
+ | 0x81b4 => -rw-rw-r-- | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | Nous utiliserons les fonctions de lecture de fichiers | ||
+ | |||
+ | <code python> | ||
+ | fs = open (" | ||
+ | | ||
+ | bytes = fs.read (len) | ||
+ | </ | ||
+ | |||
+ | Où | ||
+ | * open est la fonction qui ouvre un fichier (" | ||
+ | * seek est la fonction qui positionne le pointeur de lecture dans le fichier une adresse particulière (addr) | ||
+ | * read est la fonction qui lit un nombre d' | ||
+ | |||
+ | |||
+ | {{: | ||
+ | |||
+ | Pour voir le fichier en hexadécimal utilisez emacs et la commande : M-x hexl-mode //(Esc-x suivi de hexl-mode)// | ||
+ | |||
+ | |||
+ | Voici la structure inode en C | ||
+ | <code c> | ||
+ | | ||
+ | __u16 i_mode; | ||
+ | __u16 i_uid; | ||
+ | __u32 i_size; | ||
+ | __u32 i_time; | ||
+ | __u8 i_gid; | ||
+ | __u8 i_nlinks; | ||
+ | __u16 i_zone [9]; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | Voici comment on peut la lire en python | ||
+ | <code python> | ||
+ | import struct | ||
+ | inode_fmt = '< | ||
+ | inode_len = struct.calcsize (inode_fmt) | ||
+ | inode_unpack = struct.Struct (inode_fmt).unpack_from | ||
+ | </ | ||
+ | |||
+ | Où | ||
+ | * inode_fmt est la définition correspondant à la structure C | ||
+ | * < veut dire little endianess | ||
+ | * H veut dire entier non signé sur 2 octets | ||
+ | * I veut dire entier non signé sur 4 octets | ||
+ | * b veut dire octet nonsigné | ||
+ | * 9* veut dire 9 fois le type qui suit | ||
+ | |||
+ | Voici un exemple d' | ||
+ | <code python> | ||
+ | fs = open (" | ||
+ | fs.seek (i2addr (2), 0) | ||
+ | data = fs.read (inode_len) | ||
+ | inode = inode_unpack (data) | ||
+ | |||
+ | print inodeEntry | ||
+ | => (16893, 66, 160, 1407002500, 67, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0) | ||
+ | |||
+ | print hex (inodeEntry[0]) | ||
+ | => 0x41fd | ||
+ | | ||
+ | iMode = inodeEntry [0] | ||
+ | iUser = inodeEntry [1] | ||
+ | iSize = inodeEntry [2] | ||
+ | iTime = inodeEntry [3] | ||
+ | iGroup = inodeEntry [4] | ||
+ | iLinks = inodeEntry [5] | ||
+ | iZone = inodeEntry[6: | ||
+ | |||
+ | print "%s %d u:%d g:%d %5d %s" % \ | ||
+ | (propMode2str (iMode), iLink, iUser, iGroup, iSize, date2str (iDate)) | ||
+ | </ | ||
+ | |||
+ | Voici la structure des entrée de répertoire C | ||
+ | <code C> | ||
+ | | ||
+ | __u16 inode ; | ||
+ | char name [30]; | ||
+ | }; | ||
+ | </ | ||
+ | |||
+ | Voici comment on peut la lire en python | ||
+ | <code python> | ||
+ | import struct | ||
+ | dirEntry_fmt = '< | ||
+ | dirEntry_len = struct.calcsize (dirEntry_fmt) | ||
+ | dirEntry_unpack = struct.Struct (dirEntry_fmt).unpack_from | ||
+ | </ | ||
+ | |||
+ | Où | ||
+ | * inode_fmt est la définition correspondant à la structure C | ||
+ | * < veut dire little endianess | ||
+ | * H veut dire entier non signé sur 2 octets | ||
+ | * s est un caractère | ||
+ | * 30* veut dire 30 fois le type qui suit | ||
+ | |||
+ | Voici un exemple d' | ||
+ | <code python> | ||
+ | fs = open (" | ||
+ | fs.seek (ua2addr (5), 0) | ||
+ | data = fs.read (dir_len) | ||
+ | dirEntry = dir_unpack (data) | ||
+ | |||
+ | print dirEntry [0], dirEntry[1].rstrip (' | ||
+ | </ | ||
+ | |||
+ | ===== Mise au point de code C ===== | ||
+ | |||
+ | Il existe un outil de mise au point des programmes écrits en C ou C++ : **gdb**. | ||
+ | |||
+ | Il faut au préalable avoir compilé le vôtre avec l’option “**-g**”. Au moment de l’exécution, | ||
+ | <code bash> | ||
+ | gdb --args ./a.out A B C D | ||
+ | |||
+ | </ | ||
+ | |||
+ | Voici quelques commandes : | ||
+ | |||
+ | * Vous pouvez placer un point d' | ||
+ | * Attendre le prompt gdb et saisissez “**run**”. | ||
+ | * La commande “**where**” permet de savoir où l’on se trouve dans la pile d’exécution. | ||
+ | * La commande “**frame** | ||
+ | * Il est possible d’afficher des valeurs des variables avec la commande “**print**”. | ||
+ | |||
+ | <WRAP center round tip 60%> Toutes ces actions peuvent être réalisées sous emacs: | ||
+ | |||
+ | * M-x shell : ouvre un terminal | ||
+ | * M-x compile : lance une compilation avec un lien direct avec les erreurs | ||
+ | * M-x gdb : lance la mise au point et l' | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ====== TP4 ====== | ||
+ | |||
+ | Exemple de code pour dessiner dans un JPanel. | ||
+ | |||
+ | <code java> | ||
+ | public class Panneau extends JPanel { | ||
+ | public Panneau (int width, int height) { | ||
+ | this.width = width; | ||
+ | this.height = height; | ||
+ | Dimension size = new Dimension (width, height); | ||
+ | setMinimumSize (size); | ||
+ | setPreferredSize (size); | ||
+ | setDoubleBuffered (true); | ||
+ | } | ||
+ | |||
+ | public synchronized void update () { | ||
+ | repaint (); | ||
+ | } | ||
+ | |||
+ | public void paint (Graphics g) { | ||
+ | Toolkit.getDefaultToolkit ().sync (); | ||
+ | Graphics2D g2 = (Graphics2D) g; | ||
+ | g2.setBackground (Color.WHITE); | ||
+ | g2.clearRect (0, 0, width, height); | ||
+ | |||
+ | g2.setColor (Color.GREEN); | ||
+ | g2.fillRect (10, 10, 100, 100); | ||
+ | |||
+ | // ... | ||
+ | // | ||
+ | // | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Exemple de code pour tester un objet graphique. | ||
+ | |||
+ | <code java> | ||
+ | public static final void testComponent (final String title, final Component component) { | ||
+ | SwingUtilities.invokeLater (new Runnable () { | ||
+ | public void run () { | ||
+ | JFrame jFrame = new JFrame (title); | ||
+ | jFrame.addWindowListener (new WindowAdapter () { | ||
+ | public void windowClosing (WindowEvent e) { | ||
+ | System.exit (0); | ||
+ | } | ||
+ | }); | ||
+ | jFrame.getContentPane ().add (component, BorderLayout.CENTER); | ||
+ | jFrame.pack (); | ||
+ | Dimension screenSize = Toolkit.getDefaultToolkit ().getScreenSize (); | ||
+ | Dimension size = jFrame.getSize (); | ||
+ | jFrame.setLocation ((screenSize.width - size.width)/ | ||
+ | jFrame.setVisible (true); | ||
+ | } | ||
+ | }); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Il y a 2 possibilités | ||
+ | * soit faire un thread qui redessine le Panneau toutes les secondes et 1 thread par Rectangle à afficher | ||
+ | * soit faire que les Rectangle soit des objet graphique et donc 1 thread par Rectangle qui vont faire une demande de rafraîchissement. | ||
+ | Pour la solution objets graphique on pourra utiliser le code suivant : | ||
+ | <code java> | ||
+ | invalidate (); | ||
+ | objetGraphiqueADeplacer.setLocation (x, y); | ||
+ | validate (); | ||
+ | </ | ||
+ | |||
+ | ====== TP5 ====== | ||
+ | |||
+ | Pour le TP, vous devez télécharger {{ : | ||
+ | |||
+ | Après décompression de l' | ||
+ | |||
+ | Classes utiles pour le TP5 : | ||
+ | <code bash> | ||
+ | tp5/ | ||
+ | ├── jar | ||
+ | │ └── tp5.jar (Game.class Letter.class Player.class TestParse.class) | ||
+ | ├── src | ||
+ | │ └── tp5 | ||
+ | │ | ||
+ | └── ws | ||
+ | ├── compile.sh | ||
+ | └── launch.sh | ||
+ | </ | ||
+ | |||
+ | Vous devez modifier la classe **GameNetParse.java**. | ||
+ | Pour compiler et tester, placez vous dans ws. | ||
+ | |||
+ | |||
+ | Le lancement du programme consiste dans le test suivant (inclue dans le jar) : | ||
+ | <code java> | ||
+ | public class TestParse { | ||
+ | |||
+ | static String[] msgs = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }; | ||
+ | |||
+ | static public void main (String[] arg) { | ||
+ | Game game = new Game (); | ||
+ | GameNetParse gnp = new GameNetParse (game); | ||
+ | for (String msg : msgs) { | ||
+ | gnp.parse (msg); | ||
+ | System.err.println (); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | L' | ||
+ | <code java> | ||
+ | public class Game { | ||
+ | public void netClose (String sender) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netFull (String sender) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netGuest (String sender, String guest) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netWelcome (String sender, List< | ||
+ | System.err.print ("> | ||
+ | for (Player player : players) | ||
+ | System.err.print (" " | ||
+ | System.err.println (); | ||
+ | } | ||
+ | public void netSend (String sender, Letter letter) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netAnswer (String sender, Letter letter) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netReject (String sender, Letter letter) { | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | public void netDone (String sender, List< | ||
+ | System.err.println ("> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Vous disposez des autres classes dans le jar. | ||
+ | <code java> | ||
+ | package tp5; | ||
+ | public class Player { | ||
+ | public String name; | ||
+ | public String ip; | ||
+ | public int port; | ||
+ | |||
+ | public Player (String name, String ip, String port) { | ||
+ | this.name = name; | ||
+ | this.ip = ip; | ||
+ | this.port = Integer.parseInt (port); | ||
+ | } | ||
+ | |||
+ | public String toString () { return name+" | ||
+ | } | ||
+ | |||
+ | public class Letter { | ||
+ | public String alpha; | ||
+ | public String ip; | ||
+ | public int port; | ||
+ | |||
+ | public Letter (String alpha, String ip, String port) { | ||
+ | this.alpha = alpha; | ||
+ | this.ip = ip; | ||
+ | this.port = Integer.parseInt (port); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== TP6 ====== | ||
+ | |||
+ | Pour le TP, vous devez télécharger {{ : | ||
+ | |||
+ | Après décompression de l' | ||
+ | |||
+ | <code bash> | ||
+ | tp6/ | ||
+ | ├── jar | ||
+ | │ └── tp6.jar | ||
+ | ├── src | ||
+ | │ └── tp6 | ||
+ | │ | ||
+ | │ | ||
+ | └── ws | ||
+ | ├── compile.sh | ||
+ | ├── playNet2.sh | ||
+ | ├── playNet.sh | ||
+ | ├── playTxt2.sh | ||
+ | └── playTxt.sh | ||
+ | </ | ||
+ | |||
+ | La commande playTxt.sh vous permet de tester en mode texte. | ||
+ | |||
+ | |||
+ | Vous devez écrire la classe Java **NetCom.java** pour pouvoir lancer la commande playNet.sh. | ||
+ | |||
+ | Pour cela vous pouvez reprendre la classe recvdata.java (voir le bas de la rubrique [[codes: | ||
+ | |||
+ | Pour retrouver es information IP et port des joueurs, il existe des accesseurs dans deux classes suivantes : | ||
+ | <code java> | ||
+ | public class Player implements Comparable< | ||
+ | |||
+ | public String getName () { return name; } | ||
+ | public String getIp () { return ip; } | ||
+ | public int getPort () { return port; } | ||
+ | } | ||
+ | </ | ||
+ | <code java> | ||
+ | public class Game extends StateNotifier implements IGame { | ||
+ | public Player getOwner () { return owner;} | ||
+ | } | ||
+ | </ | ||
+ | La classe Packet quand à elle est définie dans l' | ||
+ | <code java> | ||
+ | public class Packet { | ||
+ | String ip; | ||
+ | int port; | ||
+ | String msg; | ||
+ | public Packet (String ip, int port, String msg) { | ||
+ | this.ip = ip; | ||
+ | this.port = port; | ||
+ | this.msg = msg; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | Si vous votre adresse est un IPV6 par défaut ajoutez " | ||
+ | </ | ||