Skip to content
Snippets Groups Projects
Commit 0c9d65ff authored by ivan.rigo's avatar ivan.rigo
Browse files

Final

parent 0b302e41
No related branches found
No related tags found
No related merge requests found
# SysDistribueTPGnutella # Rapport
Ce travail a été réalisé par Ivan Rigo dans le cadre du cours de système distribué de l'année 2022-23
Faire un programme en GO appliquant Gnutella utilisant REST Le but de ce travail était d'implémenter un des algorithmes vue en cours parmis une liste. Il fallait réalise l'implémentation
avec soit go ou python, et utilise REST ou les sockets pour assurer la communication entre les noeuds. Dans notre cas,la consigne
était d'implémenter Gnutella en GO, en communiquant avec un REST que nous avons mis en place.
Chaque noeud aura un directory qu'il lira au début du programme ## Information
### Ressource
Dans le programme, ils correspond au nom des fichiers contenue dans un directory propre au noeud qu'il lira lors de l'exécution, voici l'arborescence des entrepôts dans le projet
- Storage1/
- Garbage.py
- Storage2/
- Can.txt
- Garbage.py
- Storage3/
- Ham.tyt
- Important.txt
- Storage4/
- Can.txt
- Ham.txt
- Test.html
- Storage5/
- Garbage.py
- Test.html
- Storage6/
- Can.txt
- Important.txt
- Storage7/
- Ham.txt
- Important.txt
### Transmitter
Pour chaque noeud, il correspond au premier noeud l'ayant contacté. Le noeud ayant été appelé par initReq aura -1 comme transmitter
### NodePort
Nodeport correspond à 8080 + idNoeud, donc pour envoyé une requête au premier noeud, il faudra mettre 8081
### Network
Le travail réutilise la structure du slide 104 du cours, voir schemadeNode.png pour plus de clarification sur quel node possède quel id
## Route
### Côtée client
#### Initialise la recherche (GET)
http://localhost:NodePort/initReq/ttl/ressource
Active un noeud pour démarré la recherche d'une ressource
##### ttl
Représente le nombre de saut que la requête effectuera avant que les noeud arrête de la propager
##### ressource
Représente la ressource cherché, dans notre programme,c'est le nom d'un fichier
Ci-dessous une liste représentant les fichiers et leurs
##### Retour
La requête n'affichera rien sur le terminal l'ayant envoyé, cependant, le noeud ayant reçu cet appel va affiché
s'il possède la ressource sur son terminal. Il envoit ensuite une requête req contenant le ttl,la ressource et l'id du message
### Côté noeud
Ces fonctions sont utilisé entre les noeuds et ne doivent pas être appelé par l'user
#### Envoyé la recherche au voisins (GET)
http://localhost:NodePort/req/transmitter/ttl/msgid/ressource
##### transmiter
Correspond à l'id du noeud ayant envoyé la requête
##### ttl
Correspond au Time To Live, il est décremente avant de l'envoyé aux voisins autre que transmitter
##### msgId
Correspond à l'id de la recherche. Elle change à chaque fois que la route initReq est appelé
##### ressource
Représente la ressource cherché
##### Retour
Renvoie OK si tout se passe bien. La requête n'est traité qu'une fois et tout appel successive avec le même msgID renvoie OK sans exécuter le reste de la requête. Vérifie lors de la première requête s'il possède la ressource et l'envoie à son transmitter. Broadcast ensuite la requête avec un TTL décrémenté à ses voisins ormis transmitter
#### Découverte de la ressource (GET)
http://localhost:NodePort/foundReq/:finder/:ressource
##### finder
Correspond à l'id du noeud ayant l'objet dans son entrepôt
##### ressource
Représente la ressource cherché
#### Retour
Renvoie cette requête à son transmitter si le noeud actuel n'est pas le noeud ayant été appelé par initReq, sinon, affiche dans le terminal l'id du noeud possèdant la ressource
## Tester le programme
Pour tester le programme, démarré chaque noeud avec un terminal ouvert dans le dossier web-service-gin.
Pour chaque noeud, exécuté la commande : go run Gnutella.go neighbour-x.yaml, x étant l'id du noeud (entre 1 à 7)
Ouvrir un autre terminal et appelé la requête initReq ( http://localhost:NodePort/initReq/ttl/ressource)
\ No newline at end of file
schemaNode.png

74.4 KiB

...@@ -14,44 +14,24 @@ import ( ...@@ -14,44 +14,24 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
type nodeData struct { type Neighbours struct {
ID int `yaml:"id"`
Address string `yaml:"address"`
Neighbours []Neighbors `yaml:"neighbors"`
}
type Neighbors struct {
ID int `yaml:"id"` ID int `yaml:"id"`
Address string `yaml:"address"` Address string `yaml:"address"`
} }
type nodeData struct {
ID int `yaml:"id"`
Address string `yaml:"address"`
Neighbors []Neighbours `yaml:"neighbours"`
}
var data nodeData var data nodeData
var storage []string var storage []string
var idServ string
var addressCur string var addressCur string
var transmitter int var transmitter int
var msgId = 0 var msgId = 0
var err error var err error
var basePort = 8080
var assignTransM sync.Mutex var assignTransM sync.Mutex
// album represents data about a record album.
type album struct {
ID string `json:"id"`
Neighb []int `json:"price"`
}
// albums slice to seed record album data.
var albums = []album{
{ID: "1", Neighb: []int{2, 3, 4}},
{ID: "2", Neighb: []int{1, 5, 6}},
{ID: "3", Neighb: []int{1, 6, 7}},
{ID: "4", Neighb: []int{1, 7}},
{ID: "5", Neighb: []int{2, 6}},
{ID: "6", Neighb: []int{2, 3, 5}},
{ID: "7", Neighb: []int{3, 4}},
}
func getRequest(urlTxt string) { func getRequest(urlTxt string) {
resp, err := http.Get(urlTxt) resp, err := http.Get(urlTxt)
printErr(err) printErr(err)
...@@ -59,10 +39,7 @@ func getRequest(urlTxt string) { ...@@ -59,10 +39,7 @@ func getRequest(urlTxt string) {
} }
func initReq(c *gin.Context) { func initReq(c *gin.Context) {
nbIdServ, err := strconv.Atoi(idServ) msgId = rand.Intn(100) + data.ID
printErr(err)
msgId = rand.Intn(100) + nbIdServ
transmitter = -1 transmitter = -1
fmt.Println("\n Start of new research ") fmt.Println("\n Start of new research ")
for _, x := range storage { for _, x := range storage {
...@@ -71,50 +48,44 @@ func initReq(c *gin.Context) { ...@@ -71,50 +48,44 @@ func initReq(c *gin.Context) {
break break
} }
} }
for i := 0; i < len(albums); i++ { for j := 0; j < len(data.Neighbors); j++ {
if albums[i].ID == idServ { go getRequest("http://" + data.Neighbors[j].Address + "/req/" + strconv.Itoa(data.ID) + "/" + c.Param("ttl") + "/" + strconv.Itoa(msgId) + "/" + c.Param("ressource"))
for j := 0; j < len(albums[i].Neighb); j++ {
go getRequest("http://localhost:" + strconv.Itoa(basePort+albums[i].Neighb[j]) + "/req/" + idServ + "/" + c.Param("tlv") + "/" + strconv.Itoa(msgId) + "/" + c.Param("ressource"))
}
}
} }
} }
//Only treat the first call
func receiveReq(c *gin.Context) { func receiveReq(c *gin.Context) {
idMsgInt, err := strconv.Atoi(c.Param("msgId")) msgIdInt, err := strconv.Atoi(c.Param("msgId"))
printErr(err) printErr(err)
assignTransM.Lock() assignTransM.Lock()
if msgId != idMsgInt { if msgId != msgIdInt {
msgId = idMsgInt msgId = msgIdInt
assignTransM.Unlock() assignTransM.Unlock()
transmitterId, err := strconv.Atoi(c.Param("transmitter")) transmitterId, err := strconv.Atoi(c.Param("transmitter"))
printErr(err) printErr(err)
transmitter = transmitterId transmitter = getIndexById(transmitterId)
tlv, err := strconv.Atoi(c.Param("tlv")) ttl, err := strconv.Atoi(c.Param("ttl"))
printErr(err) printErr(err)
//Send to Transmitter if exist on Node
for _, x := range storage { for _, x := range storage {
if x == c.Param("ressource") { if x == c.Param("ressource") {
go getRequest("http://localhost:" + strconv.Itoa(basePort+transmitter) + "/foundReq/" + idServ + "/" + c.Param("ressource")) go getRequest("http://" + data.Neighbors[transmitter].Address + "/foundReq/" + strconv.Itoa(data.ID) + "/" + c.Param("ressource"))
break break
} }
} }
tlv = tlv - 1 ttl = ttl - 1
if tlv != 0 { if ttl != 0 {
for i := 0; i < len(albums); i++ { for j := 0; j < len(data.Neighbors); j++ {
//Open Neighb reg of this node if transmitter != j {
if albums[i].ID == idServ { go getRequest("http://" + data.Neighbors[j].Address + "/req/" + strconv.Itoa(data.ID) + "/" + strconv.Itoa(ttl) + "/" + strconv.Itoa(msgId) + "/" + c.Param("ressource"))
for j := 0; j < len(albums[i].Neighb); j++ {
if transmitter != albums[i].Neighb[j] {
getRequest("http://localhost:" + strconv.Itoa(basePort+albums[i].Neighb[j]) + "/req/" + idServ + "/" + strconv.Itoa(tlv) + "/" + strconv.Itoa(msgId) + "/" + c.Param("ressource"))
}
}
} }
} }
} }
} else { } else {
assignTransM.Unlock() assignTransM.Unlock()
...@@ -124,14 +95,23 @@ func receiveReq(c *gin.Context) { ...@@ -124,14 +95,23 @@ func receiveReq(c *gin.Context) {
//Called by child when ressource is find //Called by child when ressource is find
func foundReq(c *gin.Context) { func foundReq(c *gin.Context) {
finderNb, err := strconv.Atoi(c.Param("finder"))
printErr(err)
portFinder := strconv.Itoa(basePort + finderNb)
if transmitter == -1 { if transmitter == -1 {
fmt.Println("\n Instance of " + c.Param("ressource") + " found in " + portFinder) fmt.Println("\n Instance of " + c.Param("ressource") + " found on port " + c.Param("finder"))
} else { } else {
getRequest("http://localhost:" + strconv.Itoa(basePort+transmitter) + "/foundReq/" + c.Param("finder") + "/" + c.Param("ressource")) getRequest("http://" + data.Neighbors[transmitter].Address + "/foundReq/" + c.Param("finder") + "/" + c.Param("ressource"))
}
}
//Return the index of neighbour port in local db
func getIndexById(idNode int) int {
for i := 0; i < len(data.Neighbors); i++ {
if idNode == data.Neighbors[i].ID {
return i
}
} }
fmt.Println("ID cannot be found in Neighbour Database, this shouldnt show up")
os.Exit(1)
return 0
} }
func printErr(err error) { func printErr(err error) {
...@@ -143,27 +123,25 @@ func printErr(err error) { ...@@ -143,27 +123,25 @@ func printErr(err error) {
func main() { func main() {
neighborsFile := os.Args[1] //Reading Yaml
idServ = os.Args[2] neighboursFile := os.Args[1]
buf, err := ioutil.ReadFile(neighborsFile) buf, err := os.ReadFile(neighboursFile)
err = yaml.Unmarshal(buf, &data) err = yaml.Unmarshal(buf, &data)
printErr(err) printErr(err)
addressCur = data.Address
/* //Filling Storage
nbIdServ, err := strconv.Atoi(idServ) files, err := ioutil.ReadDir("Storage" + strconv.Itoa(data.ID) + "/")
files, err := ioutil.ReadDir("Storage" + idServ + "/") printErr(err)
printErr(err)
for _, file := range files { for _, file := range files {
storage = append(storage, file.Name()) storage = append(storage, file.Name())
} }
router := gin.Default()
router.GET("/initReq/:ttl/:ressource", initReq)
router.GET("/req/:transmitter/:ttl/:msgId/:ressource", receiveReq)
router.GET("/foundReq/:finder/:ressource", foundReq)
router := gin.Default() router.Run(data.Address)
router.GET("/initReq/:tlv/:ressource", initReq)
router.GET("/req/:transmitter/:tlv/:msgId/:ressource", receiveReq)
router.GET("/foundReq/:finder/:ressource", foundReq)
router.Run("localhost:" + strconv.Itoa(basePort+nbIdServ))
*/
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment