Last active
December 22, 2024 00:55
-
-
Save Samu31Nd/6d55ccab50555304e759f3b3a36e1220 to your computer and use it in GitHub Desktop.
GBN in Go - example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| type typeMessage int8 | |
| const ( | |
| ErrorCommunication typeMessage = iota - 1 | |
| StartCommunication | |
| ContinueCommunication | |
| EndCommunication | |
| ) | |
| type PackageType struct { | |
| MessageType typeMessage `json:"id"` | |
| Message string `json:"content"` | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| //SERVER | |
| import ( | |
| "encoding/json" | |
| "fmt" | |
| "log" | |
| "net" | |
| "strconv" | |
| "time" | |
| ) | |
| const ( | |
| timeoutReceiver = 3 * time.Second | |
| WsR = 4 | |
| ACK = "ACK" | |
| ) | |
| var addr = net.UDPAddr{ | |
| IP: net.IPv4(127, 0, 0, 1), | |
| Port: 8080, | |
| } | |
| func main() { | |
| conn, err := net.ListenUDP("udp", &addr) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| defer func(conn *net.UDPConn) { | |
| err := conn.Close() | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| }(conn) | |
| fmt.Printf("Server UDP listening in: [%s]\n", addr.String()) | |
| buffer := make([]byte, 1024) | |
| for { | |
| err = conn.SetReadDeadline(time.Time{}) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| n, clientAddr, err := conn.ReadFromUDP(buffer) | |
| if err != nil { | |
| log.Fatal("Error trying to connect: " + err.Error()) | |
| return | |
| } | |
| var message PackageType | |
| err = json.Unmarshal(buffer[:n], &message) | |
| if err != nil { | |
| fmt.Println("Error deserializando datos:", err) | |
| return | |
| } | |
| fmt.Printf("Recibido: [%s] desde [%s]\nStarting communication...\n", message.Message, clientAddr.String()) | |
| response := PackageType{ | |
| MessageType: StartCommunication, | |
| Message: "ACK", | |
| } | |
| data, _ := json.Marshal(response) | |
| _, err = conn.WriteToUDP(data, clientAddr) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| receivePackages(conn, clientAddr) | |
| } | |
| } | |
| // TODO: guardar en un arreglo | |
| func receivePackages(conn *net.UDPConn, clientAddr *net.UDPAddr) { | |
| //expecting that almost 1 package will be sent, after this will change | |
| buffer := make([]byte, 1024) | |
| var message PackageType | |
| var window [WsR]int | |
| err := conn.SetReadDeadline(time.Now().Add(timeoutReceiver)) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| lastNum := 1 | |
| endOfCommunication := false | |
| for !endOfCommunication { | |
| //receive | |
| var i = 0 | |
| for ; i < WsR; i++ { | |
| n, _, err := conn.ReadFromUDP(buffer) | |
| if err != nil { | |
| fmt.Println("Message don't received correctly...") | |
| log.Fatal(err) | |
| return | |
| } | |
| err = json.Unmarshal(buffer[:n], &message) | |
| if err != nil { | |
| fmt.Println("Error deserializando datos:", err) | |
| return | |
| } | |
| numberReceived, _ := strconv.Atoi(message.Message) | |
| if numberReceived == lastNum { | |
| lastNum++ | |
| } | |
| window[i] = lastNum - 1 | |
| if message.MessageType == EndCommunication { | |
| endOfCommunication = true | |
| break | |
| } | |
| } | |
| //send | |
| for j := 0; j < WsR; j++ { | |
| messageToSend := PackageType{ | |
| MessageType: ContinueCommunication, | |
| Message: strconv.Itoa(window[j]), | |
| } | |
| data, _ := json.Marshal(messageToSend) | |
| _, err := conn.WriteToUDP(data, clientAddr) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| } | |
| } | |
| fmt.Println("Transference correctly!") | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| //CLIENT | |
| import ( | |
| "encoding/json" | |
| "fmt" | |
| "log" | |
| "net" | |
| "strconv" | |
| "time" | |
| ) | |
| const ( | |
| WsS = 4 | |
| timeoutSender = 3 * time.Second | |
| ) | |
| func main() { | |
| fmt.Println("Insert the amount of packages you want to send: ") | |
| var packages int | |
| fmt.Scanf("%d", &packages) | |
| conn, err := net.Dial("udp", "127.0.0.1:8080") | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| defer func(conn net.Conn) { | |
| err := conn.Close() | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| }(conn) | |
| fmt.Println("Starting communication with server...") | |
| message := PackageType{ | |
| MessageType: StartCommunication, | |
| Message: "START", | |
| } | |
| data, _ := json.Marshal(message) | |
| _, err = conn.Write(data) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| fmt.Println("START sent, waiting ACK...") | |
| buffer := make([]byte, 1024) | |
| n, err := conn.Read(buffer) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| var messageReceived PackageType | |
| err = json.Unmarshal(buffer[:n], &messageReceived) | |
| if err != nil { | |
| fmt.Println("Error deserializando datos:", err) | |
| return | |
| } | |
| if messageReceived.Message != "ACK" { | |
| fmt.Println("ACK not received from the communication, instead we got: ", messageReceived.MessageType) | |
| return | |
| } | |
| fmt.Printf("[START] sended to server successfully!\nStarting sending lot of packages...\n") | |
| gbnSender(conn, packages) | |
| } | |
| func gbnSender(conn net.Conn, noPackages int) { | |
| packages := createPackages(noPackages) | |
| var window [WsS]PackageType | |
| buffer := make([]byte, 1024) | |
| fmt.Println(packages) | |
| for base := 0; base < noPackages; { | |
| fmt.Printf("Condition: [%d]\n", base+WsS) | |
| for nextSeqNum := base; nextSeqNum < base+WsS; nextSeqNum++ { | |
| //sending the next 4 | |
| window[nextSeqNum%WsS] = packages[nextSeqNum] | |
| //serial | |
| data, _ := json.Marshal(window[nextSeqNum%WsS]) | |
| _, err := conn.Write(data) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| fmt.Println("Package sent: ", packages[nextSeqNum]) | |
| if packages[nextSeqNum].MessageType == EndCommunication { | |
| break | |
| } | |
| } | |
| //receiving the 4 next ACKs | |
| err := conn.SetReadDeadline(time.Now().Add(timeoutSender)) | |
| if err != nil { | |
| log.Fatal(err) | |
| return | |
| } | |
| for nextAckNum := 0; nextAckNum < WsS; nextAckNum++ { | |
| n, err := conn.Read(buffer) | |
| if err != nil { | |
| fmt.Println("Timeout, sending again window...") | |
| break | |
| } | |
| var messageReceived PackageType | |
| err = json.Unmarshal(buffer[:n], &messageReceived) | |
| if err != nil { | |
| fmt.Println("Error deserializando datos:", err) | |
| return | |
| } | |
| num, _ := strconv.Atoi(messageReceived.Message) | |
| fmt.Printf("-Recieved %d from reciever\n", num) | |
| if num == base+1 { | |
| base++ | |
| } | |
| } | |
| } | |
| } | |
| func createPackages(noPackages int) []PackageType { | |
| var packages []PackageType | |
| packages = make([]PackageType, noPackages) | |
| for i := 0; i < noPackages; i++ { | |
| packages[i] = PackageType{ | |
| ContinueCommunication, | |
| fmt.Sprintf("%d", i+1), | |
| } | |
| } | |
| packages[noPackages-1].MessageType = EndCommunication | |
| return packages | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment