Skip to content

Instantly share code, notes, and snippets.

@Samu31Nd
Last active December 22, 2024 00:55
Show Gist options
  • Select an option

  • Save Samu31Nd/6d55ccab50555304e759f3b3a36e1220 to your computer and use it in GitHub Desktop.

Select an option

Save Samu31Nd/6d55ccab50555304e759f3b3a36e1220 to your computer and use it in GitHub Desktop.
GBN in Go - example
package main
type typeMessage int8
const (
ErrorCommunication typeMessage = iota - 1
StartCommunication
ContinueCommunication
EndCommunication
)
type PackageType struct {
MessageType typeMessage `json:"id"`
Message string `json:"content"`
}
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!")
}
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