The essence of the Go language • [Chapter 5 A small example of concurrency in the go Bible]

Modify clock2 to support incoming parameters as port numbers, and then write a clockwall program that can communicate with multiple clock servers at the same time, read time from multiple servers, and display the results returned by all services at once in a table , Similar to the clock wall you see in some offices. If you have geographically distributed servers that can be used, let these servers run on different machines; or run multiple different instances on the same machine, these instances listen to different ports, pretending to be in different time zones . Like this:

$ TZ=US/Eastern    ./clock2 -port 8010 &
$ TZ=Asia/Tokyo    ./clock2 -port 8020 &
$ TZ=Europe/London ./clock2 -port 8030 &
$ clockwall NewYork=localhost:8010 Tokyo=localhost:8020 London=localhost:8030

Server code, support go run pass parameter to start multiple servers

$ go run clock2.go -port 9090 -city beijing

$ go run clock2.go -port 9089 -city shanghai

/clock2.go

package main

import (
	"io"
	"log"
	"net"
	"time"
	"strconv"
	"fmt"
	"flag"
)
var port string
var city string

func init() {
    flag.StringVar(&port,"port","default","8090")
	flag.StringVar(&city,"city","default","default")
}

func main() {
	flag.Parse()//暂停获取参数
	fmt.Println(port)
	fmt.Println(city)
	listenConn(port)
}

func handleConn(conn net.Conn) {
	defer conn.Close()
	for {
		_, err := io.WriteString(conn, city + time.Now().Format("15:34:09\n"))
		if err != nil {
			return
		}
		time.Sleep(1 * time.Second)
	}
}

func listenConn(port string){
	listener, err := net.Listen("tcp", "localhost:" + port)
	if err != nil {
		log.Fatal(err)
		fmt.Print(err)
	}
	i := 0
	for {
		conn, err := listener.Accept()
		i++
		fmt.Println("get new conn" + strconv.Itoa(i))
		if err != nil {
			log.Print(err)
			continue
		}

		go handleConn(conn)
	}
}

Client code, paste your first try code first

package main

import(
	"io"
	"log"
	"net"
	"os"
	"flag"
	"strings"
	"fmt"
)

var port string

func init() {
    flag.StringVar(&port,"port","default","8090")
	
}
func main(){
flag.Parse()//暂停获取参数
	a := strings.Split(port, ";")
	for _,v := range a{
		fmt.Println(v)
		go portDial(v)
	}
}

func mustCopy(dst io.Writer,src io.Reader){
	if _,err := io.Copy(dst,src);err != nil{
		log.Fatal(err)
	
	}
}

func portDial(po string){

	conn,err:= net.Dial("tcp","localhost:" + po)
	if err!= nil{
		log.Fatal(err)
	}
	
	defer conn.Close()
	mustCopy(os.Stdout,conn)
}

Nothing was printed out this time, because the main thread directly exited. I will not consider the channel for the time being. I will loop or pause the main thread for 10 seconds to see the effect. The improved code is as follows:

package main

import(
	"io"
	"log"
	"net"
	"os"
	"flag"
	"strings"
	"fmt"
	"time"
)

var port string

func init() {
    flag.StringVar(&port,"port","default","8090")
	
}
func main(){
flag.Parse()//暂停获取参数
fmt.Println(port)
	a := strings.Split(port, ",")
	fmt.Println(a)
	for _,v := range a{
		fmt.Println(v)
		go portDial(v)
	}
	
	for{
		time.Sleep(10 * time.Second)
	}
}

func mustCopy(dst io.Writer,src io.Reader){
	if _,err := io.Copy(dst,src);err != nil{
		log.Fatal(err)
	
	}
}

func portDial(po string){

	conn,err:= net.Dial("tcp","localhost:" + po)
	if err!= nil{
		log.Fatal(err)
	}
	
	defer conn.Close()
	mustCopy(os.Stdout,conn)
}

$ go run netcat.go -port 9090;9089

You get the expected result:

In addition, I saw a similar client implementation on the Internet

// Netcat1 is a read-only TCP client.
package main
 
import (
        "io"
        "log"
        "net"
        "os"
        "strings"
        "time"
)
 
func main() {
        for _, v := range os.Args[1:] {
                keyValue := strings.Split(v, "=")
                go connTcp(keyValue[1])
        }  
        for {
                time.Sleep(1 * time.Second)
        }  
}
 
func connTcp(uri string) {
        conn, err := net.Dial("tcp", uri)
        if err != nil {
                log.Fatal(err)
        }  
        defer conn.Close()
        mustCopy(os.Stdout, conn)
}
 
func mustCopy(dst io.Writer, src io.Reader) {
        if _, err := io.Copy(dst, src); err != nil {
                log.Fatal(err)
        }  
}

$ go run netcat1.go beijing=localhost:9090 hangzhou=localhost:9089

Can also get the expected result

Note:

*io.Copy()  Methods copies from  src copy to  dst , until  src reach the end of file (EOF) or an error occurs, then returns the first error (if any) encountered when the number of bytes copied and copied;

func Copy(dst Writer, src Reader) (written int64, err error)

Stdin io.Reader  The input of the
 Stdout io.Writer command process The output of the
 Stderr io.Writer command process The error output of the command process

* The type of os.Args [1:] is  [] string  , which is a string slice. Can directly get the parameters after go run, with spaces as the separator of multiple elements

os.Args [0:] will include the path of the program itself + parameters separated by spaces 

 https://www.cnblogs.com/taoshihan/p/8955365.html

 

Published 7 original articles · Liked5 · Visits 272

Guess you like

Origin blog.csdn.net/weixin_38193228/article/details/105548388