服务端客户端使用Go协程通信

服务端客户端使用Go协程通信

  • 服务端
  • 客户端
  • 测试

服务端

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

func main() {
	//TODO 1. 监听端口
	//TODO 2. 接收连接
	//TODO 3. 处理数据
	//TODO 4. 资源关闭 延时关闭
	listen, err := net.Listen("tcp", "127.0.0.1:8989")
	if err != nil {
		fmt.Println("监听端口失败,退出程序...,error:", err)
		return
	}
	//2. 延时关闭listen
	defer func() { _ = listen.Close() }()

	var conn net.Conn
mainOut01:
	for {
		// 阻塞
		conn, err = listen.Accept()
		// 延时关闭
		if err != nil {
			fmt.Println("获取conn失败,error: ", err)
			break mainOut01
		}
		fmt.Println(conn.RemoteAddr(), " connected the server ... ")
		//处理数据
		go ServerReceiveDataSolve(conn)
		go ServerSendData(conn)

	}
}

func ServerReceiveDataSolve(conn net.Conn) {
	// 读写一起使用的话,关闭一个,另外就不能用了
	// 延时关闭
	//defer func() { _ = conn.Close() }()
	for {
		// 1. 使用切片变量来装载字节数据
		bytes := make([]byte, 1024)
		readLen, err := conn.Read(bytes)
		if err != nil {
			fmt.Println("读取数据出现异常,error is: ", err)
			fmt.Println("客户端断开...")
			return
		}
		content := string(bytes[0:readLen])
		fmt.Printf("读到的数据内容为-:%v", content)
		if content == "quit\r\n" {
			fmt.Println("服务器端接收数据协程关闭")
			break
		}
	}
}

func ServerSendData(conn net.Conn) {
	// 延时关闭
	//defer func() { _ = conn.Close() }()
	for true {
		stdin := os.Stdin
		reader := bufio.NewReader(stdin)
		data, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("从终端获取数据失败, error is:", err)
		}
		byteSize, err := conn.Write([]byte(data))
		if err != nil {
			fmt.Println("服务端发送数据失败,error is:", err)
		}
		fmt.Println("服务端发送的内容为:", data, " 其字节大小(包含\\r\\n)为:", byteSize)
		if data == "quit\r\n" {
			fmt.Println("服务器端发送数据协程关闭")
			break
		}
	}
}

客户端

package main

import (
	"bufio"
	"fmt"
	"net"
	"os"
)

var (
	exetChannel = make(chan bool, 2)
)

func main() {
	// 与服务端获取连接
	conn, err := net.Dial("tcp", "127.0.0.1:8989")
	if err != nil {
		fmt.Println("获取连接失败,退出程序... error is:", err)
		return
	}
	// 延时关闭
	defer func() { _ = conn.Close() }()
	//处理数据
	go ClientSendData(conn)
	// ClientReceiveDataSolve(conn)
	go ClientReceiveDataSolve(conn)

	for {
		if len(exetChannel) == 2 {
			<-exetChannel
			<-exetChannel
			break
		}
	}
}

func ClientSendData(conn net.Conn) {
	for true {
		stdin := os.Stdin
		reader := bufio.NewReader(stdin)
		data, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("从终端获取数据失败, error is:", err)
		}
		byteSize, err := conn.Write([]byte(data))
		if err != nil {
			fmt.Println("客户端发送数据失败,error is:", err)
		}
		fmt.Println("客户端发送的内容为:", data, " 其字节大小(包含\\r\\n)为:", byteSize)
		if data == "quit\r\n" {
			fmt.Println("客户端的发送协程关闭")
			//_, _ = conn.Write([]byte("quit\r\n"))
			exetChannel <- true
			break
		}
	}
}

func ClientReceiveDataSolve(conn net.Conn) {
	for {
		bytes := make([]byte, 1024)
		nBytes, err := conn.Read(bytes)
		if err != nil {
			//if err == io.EOF {
			fmt.Println("客户端读取数据失败,error is:", err)
			break
		}
		fmt.Println("客户端读取到的内容为:", string(bytes[:nBytes]), "大小为:", nBytes)
		if string(bytes[0:nBytes]) == "quit\r\n" {
			fmt.Println("客户端的接收协程关闭")
			//_, _ = conn.Write([]byte("quit\r\n"))
			exetChannel <- true
			return
		}
	}
}

测试

服务端客户端使用Go协程通信_第1张图片

你可能感兴趣的:(golang,服务器,开发语言)