go学习(8)TCP编程

go网络编程简单易上手,tcp可以很容易实现一个客户端一个线程(goroutine),业务处理清楚明了。

服务端:

package main

import (
	"fmt"
	"net"
)

const (
	MAX_MSG_LENGTH = 1024 //每次最大收多少数据
)

//处理玩家数据
func Echo(c net.Conn) {
	fmt.Printf("Client conn %s", c.RemoteAddr().String())
	data := make([]byte, MAX_MSG_LENGTH) //用于接收数据缓冲
	defer c.Close()                      //defer 关闭连接

	for { //循环处理客户端数据
		data = []byte{}
		n, err := c.Read(data) //这里阻塞等到客户端数据到来
		if err != nil {
			fmt.Printf("Read message failed:%s\n", err.Error())
			return
		}

		if n > 0 {
			c.Write(data) //将客户端的数据发送回去
		}
	}
}

func main() {
	fmt.Printf("Server is ready...\n")
	l, err := net.Listen("tcp", ":7777") //绑定协议,端口
	if err != nil {
		fmt.Printf("Failure to listen:%s\n", err.Error())
		return
	}

	for {
		if c, err := l.Accept(); err == nil { //接受连接
			go Echo(c) //每一个Client启动一个协程,处理数据
		}
	}
}

客户端:

package main

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

//客户端类
type Client struct {
	conn1   net.Conn //连接
	isAlive bool     //是否活跃
	sendStr chan string
	recvStr chan string
}

//客户端的连接函数
func (c *Client) Connect() bool {
	if c.isAlive { //已经连接成功
		return true
	} else {
		var err error
		c.conn1, err = net.Dial("tcp", "127.0.0.1:7777") //连接服务端

		if err != nil {
			fmt.Printf("Failure to connect:%s\n", err.Error())
			return false
		}

		c.isAlive = true
	}

	return true
}

//发送数据接口
func (c *Client) Echo() {
	line := <-c.sendStr         //line为要发送的数据(从发送管道取数据)
	c.conn1.Write([]byte(line)) //转为byte[]发送

	buf := make([]byte, 1024)
	n, err := c.conn1.Read(buf) //等待服务端返回数据
	if err != nil {
		c.recvStr <- string("Server close...")
		c.conn1.Close()
		c.isAlive = false
		return
	}

	time.Sleep(1 * time.Second)
	c.recvStr <- string(buf[0:n]) //收到的数据写入管道recvStr
}

func Work(tc *Client) {
	if !tc.isAlive {
		if tc.Connect() {
			tc.Echo()
		} else {
			<-tc.sendStr
			tc.recvStr <- string("Server close...")
		}
	} else {
		tc.Echo()
	}
}

func main() {
	var tc Client                  //客户端实例
	tc.sendStr = make(chan string) //创建发送、接收管道
	tc.recvStr = make(chan string)

	if !tc.Connect() {
		return
	}

	r := bufio.NewReader(os.Stdin) //从命令行接收数据
	for {
		switch line, ok := r.ReadString('\n'); true { //读到换行线束
		case ok != nil:
			fmt.Printf("bye bye!\n")
			return
		default:
			go Work(&tc)
			tc.sendStr <- line
			s := <-tc.recvStr //等待接收到数据,这里会阻塞到有数据为止
			fmt.Printf("recv:%s\n", s)
		}
	}
}

猜你喜欢

转载自blog.csdn.net/ltk80/article/details/82911944