tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/examples/net/snake/main.go (about)

     1  // This example is the classic snake network test.  The snake is feed a steady
     2  // diet of pkts and the pkts work themselves thru the snake segments and exit
     3  // the tail.  Each snake segment is a TCP socket connection to a server.  The
     4  // server echos pkts received back to the snake, and serves each segment on a
     5  // different port.  (See server/main.go for server).
     6  //
     7  //                snake     |    server
     8  //                          |
     9  //            head ----->---|-->--+
    10  //             seg a        |     |
    11  //                    +---<-|--<--+
    12  //                    |     |
    13  //                    +-->--|-->--+
    14  //             seg b        |     |
    15  //                    +---<-|--<--+
    16  //                    |     |
    17  //                    +-->--|-->--+
    18  //             seg c        |     |
    19  //                    +---<-|--<--+
    20  //                    |     |
    21  //                    +-->--|-->--+
    22  //              ...         |     |
    23  //                    +---<-|--<--+
    24  //                    |     |
    25  //                    +-->--|-->--+
    26  //             seg n        |     |
    27  //            tail -------<-|--<--+
    28  //                          |
    29  
    30  // The snake segments are linked by channels and each segment is run as a go
    31  // func.  This forces segments to connect and run concurrently, which is a good
    32  // test of the underlying driver's ability to handle concurrent connections.
    33  
    34  //go:build ninafw || wioterminal
    35  
    36  package main
    37  
    38  import (
    39  	_ "embed"
    40  	"fmt"
    41  	"log"
    42  	"net"
    43  	"strings"
    44  	"time"
    45  )
    46  
    47  //go:embed main.go
    48  var code string
    49  
    50  var (
    51  	server string = "10.0.0.100:8080"
    52  )
    53  
    54  func segment(in chan []byte, out chan []byte) {
    55  	var buf [512]byte
    56  	for {
    57  		c, err := net.Dial("tcp", server)
    58  		for ; err != nil; c, err = net.Dial("tcp", server) {
    59  			println(err.Error())
    60  			time.Sleep(5 * time.Second)
    61  		}
    62  		for {
    63  			select {
    64  			case msg := <-in:
    65  				_, err := c.Write(msg)
    66  				if err != nil {
    67  					log.Fatal(err.Error())
    68  				}
    69  				time.Sleep(100 * time.Millisecond)
    70  				n, err := c.Read(buf[:])
    71  				if err != nil {
    72  					log.Fatal(err.Error())
    73  				}
    74  				out <- buf[:n]
    75  			}
    76  		}
    77  	}
    78  }
    79  
    80  func feedit(head chan []byte) {
    81  	for i := 0; i < 100; i++ {
    82  		head <- []byte(fmt.Sprintf("\n---%d---\n", i))
    83  		for _, line := range strings.Split(code, "\n") {
    84  			if len(line) == 0 {
    85  				line = " "
    86  			}
    87  			head <- []byte(line)
    88  		}
    89  	}
    90  }
    91  
    92  var head = make(chan []byte)
    93  var a = make(chan []byte)
    94  var b = make(chan []byte)
    95  var c = make(chan []byte)
    96  var d = make(chan []byte)
    97  var e = make(chan []byte)
    98  var f = make(chan []byte)
    99  var tail = make(chan []byte)
   100  
   101  func main() {
   102  
   103  	// The snake
   104  	go segment(head, a)
   105  	go segment(a, b)
   106  	go segment(b, c)
   107  	go segment(c, d)
   108  	go segment(d, e)
   109  	go segment(e, f)
   110  	go segment(f, tail)
   111  
   112  	go feedit(head)
   113  
   114  	for {
   115  		select {
   116  		case msg := <-tail:
   117  			println(string(msg))
   118  		}
   119  	}
   120  }