0
点赞
收藏
分享

微信扫一扫

Power BI报告在PPT中实时刷新的实现技巧分享

雨鸣静声 2小时前 阅读 2

go并发编程以及socket通信的理解

文章目录

一、管道的简单使用

" golang不是通过共享内存来通信,而是通过通信来共享内存 "

1、go简单初始化

// golang不是通过共享内存来通信,而是通过通信来共享内存
func a1() {
	// 声明初始化 channel
	var ch chan string = make(chan string) // deadlock 会造成死锁,因为我们的管道是没有缓冲的
	// 内置的make函数有什么作用?
	// make 初始化内存,并且返回引用类型本身
	// new 只是将内存清零,返回的是指向类型的指针
	ch <- "hello" //阻塞写
	str := <-ch   //阻塞读
	fmt.Println(str)
	// 单向channel
	var ch1 chan<- string // 只能写
	var ch2 <-chan string // 只能读
	// 关闭channel
	close(ch1)
	x, ok := <-ch2
	if ok {
		fmt.Println(x)
	} else {
		fmt.Println("channel is closed")
	}
}

2、用 select 做一个简单的超时管理

	// Go语言直接引入select关键字,用于处理异步问题
	var ch1, ch2 chan string
	select {
	case x := <-ch1: // 如果从ch1读取数据,那么执行此语句
		fmt.Println(x)
	case y := <-ch2: // 如果从ch2读取数据,那么执行此语句
		fmt.Println(y)
	default:
		fmt.Println("default")
	}

超时管理:

func download(ch chan string) {
	for i := 1; i < 10; i++ {
		fmt.Println(i)
		time.Sleep(time.Second * 1)
	}
	ch <- "ok"
}
func a2() {
	// 超时处理
	timeout := make(chan int, 1)
	go func() {
		time.Sleep(time.Second * 3)
		timeout <- 1 // 用来标记超时,可以是任何非0值
	}()
	ch := make(chan string, 6) // 用于从download中接受数据
	go download(ch)
	select {
	case <-ch:
		fmt.Println("从ch中读取数据,执行正常业务处理") // 如果从ch中读取到数据那么正常处理业务
	case <-timeout:
		fmt.Println("3秒内没有从ch中读取数据,执行超时处理")// 如果从timeout中读取到数据,那么download执行超时
	}
}

3、编程体:通过go协程输出100个以内的任意两个数之和,减少等待。

func add(i, x, y int) {
	fmt.Printf("%d + %d = %d\n", x, y, x+y)
}
func a3() {
	for i := 1; i <= 100; i++ {
		x := rand.Intn(100)
		time.Sleep(time.Millisecond)
		y := rand.Intn(100)
		go add(i, x, y)
	}
}

二、go中的socket实现通信

// 共享数据机制-sync
func s1() {
	// sync.Mutex
	//mutex := sync.Mutex{}

}

// 上下文机制 - Context

// socket 原理
/*
	互联网TCP/IP四层模型
	四层:数据层(帧)、网络层(IP)、传输层(TCP/UDP)、应用层(HTTP)
	通信:封包和解包
	抽象:应用程序到应用程序、进程到进程、主机到主机、设备到设备

*/

1、代码示例clinet.go和server.go

package main
import (
	"bufio"
	"fmt"
	"net"
	"time"
)
func main() {
	// 与服务端建立连接
	conn, err := net.DialTimeout("tcp", "127.0.0.1:8899", time.Second)
	if err != nil {
		fmt.Printf("dial failed, err:%v\n", err)
		return
	}
	defer conn.Close()
	// 要发送的数据
	msg := []string{"hello world!", "golang", "c++", "python"}
	//  通过bufio方式发送
	writer := bufio.NewWriter(conn)
	for i, v := range msg {
		n, err := writer.Write([]byte(v))
		writer.Flush()
		if err != nil {
			fmt.Printf("write failed, err:%v\n", err)
			return
		}
		fmt.Printf("%d: write %d,bytes, data:%s\n", i, n, v)
		time.Sleep(time.Second)
	}
}
// go 基于 socket 的 tcp 编程
func HandleConn(conn net.Conn) {
	fmt.Println("accepted a new connection!")
	defer conn.Close()
	for {
		// 负责缓存接受的数据
		buf := make([]byte, 32)
		n, err := conn.Read(buf) //表面上是 阻塞读
		if err != nil {
			fmt.Println("read err:", err)
			break
		}
		if n == 0 {
			continue
		}
		// 打印客户端发送的数据
		fmt.Printf("recv client data: %s\n", string(buf[:n]))
		// 发送数据给客户端
		conn.Write([]byte("hello client"))
	}
}
func main() {
	// 开始监听 8899 端口
	listen, err := net.Listen("tcp", ":8899")
	if err != nil {
		fmt.Println("listen err:", err)
		return
	}
	// 循环接受连接
	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("accept err:", err)
			break
		}
		// 处理连接
		go HandleConn(conn)
	}
}

2、go基于 socket 的 tcp 编程

1、连接建立问题
连接拒绝:网络ping不通、ip或port指定错误、server未启动
listen backlog:增大server端listen backlog队列
网络延迟较大
2、读数据问题
无数据可读:goroutine阻塞即可
数据不足
超时
3、写数据问题
写阻塞
写入部分数据
4、线程安全问题

举报

相关推荐

0 条评论