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