La esencia del lenguaje Go • [Capítulo 5 Un pequeño ejemplo de concurrencia en la Biblia go]

Modifique clock2 para admitir parámetros entrantes como números de puerto y luego escriba un programa de wallwall que pueda comunicarse con varios servidores de reloj al mismo tiempo, lea el tiempo de varios servidores y muestre los resultados devueltos por todos los servicios a la vez en una tabla , Similar a la pared del reloj que ves en algunas oficinas. Si tiene servidores distribuidos geográficamente que se pueden usar, deje que estos servidores se ejecuten en máquinas diferentes; o ejecute varias instancias diferentes en la misma máquina, estas instancias escuchan puertos diferentes, pretendiendo estar en diferentes zonas horarias . Así:

$ 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

Código del servidor, admite el parámetro ir a pasar para iniciar varios servidores

$ 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)
	}
}

Código de cliente, pegue su primer código de prueba primero

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)
}

Esta vez no se imprimió nada porque el subproceso principal salió directamente. No consideraré el canal por el momento. Realizaré un bucle o haré una pausa en el subproceso principal durante 10 segundos para ver el efecto. El código mejorado es el siguiente:

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

Obtienes el resultado esperado:

Además, vi una implementación de cliente similar en 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

También puede obtener el resultado esperado

Nota:

*io.Copy()  Métodos copias de  src copia a  dst , hasta que  src alcance el final del archivo (EOF) o se produce un error, a continuación, devuelve el primer error (si existe) encontrado cuando el número de bytes copiados y copiadas;

Func Copy (dst Writer, src Reader) (escrito int64, error de error)

Stdin io.Reader  La entrada del
 Stdout io.Writer proceso de comando La salida del
 Stderr io.Writer proceso de comando La salida de error del proceso de comando

* El tipo de os.Args [1:] es  [] string  , que es un segmento de cadena. Puede obtener directamente los parámetros después de la ejecución, con espacios como separador de múltiples elementos

os.Args [0:] incluirá la ruta del programa en sí + parámetros separados por espacios 

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

 

Publicado 7 artículos originales · Me gusta5 · Visitas 272

Supongo que te gusta

Origin blog.csdn.net/weixin_38193228/article/details/105548388
Recomendado
Clasificación