CS // 客户端到服务器
SC // 服务器到客户端
proto:
type csproto struct {
// 两个数字
a int
b int
}
type scproto struct {
// 结果
ans int
}
// 判断是什么指令协议在更上一层
type data name {
msg_id int // 操作id
msg_data []byte // 前一个协议的字节数据
}
先调用服务器端TCPServerStart
再调用客户端TCPClientStrat
接着即可在服务器端输入数据获得结果
ex:
TCPServerStart("127.0.0.1:9099")
TCPClientStrat("127.0.0.1:9099")
package Tcp
import (
proto "../tcp_proto"
"bufio"
"encoding/json"
"fmt"
"io"
. "net"
)
const (
Add int = 0
Sub int = 1
Mul int = 2
Div int = 3
)
type csproto struct {
A int `json:"a"` // json 用法, 大写才能被识别,使用`json:"a"`可以将其变成小写
B int `json:"b"`
}
type scproto struct {
Ans int `json:"ans"`
}
type client struct {
ch chan msg
conn Conn
}
type msg struct {
Msg_id int
Data []byte
}
type cliMsg struct {
cli client
msg_id int
data []byte
}
func (cli client)send(ch chan msg){
for {
send_msg := <-ch
msg_id, data := send_msg.Msg_id, send_msg.Data
fmt.Println("send", msg_id)
data, err := proto.Packet(msg_id, data)
if err != nil {
fmt.Println("Packet fail, err:", err)
return
}
cli.conn.Write(data)
}
}
func (cli client)receive(ch chan cliMsg){
defer cli.conn.Close() // 关闭连接
reader := bufio.NewReader(cli.conn)
for {
msg_id, data_byte, err := proto.Unpack(reader)
if err == io.EOF{
return
}
if err != nil{
fmt.Println("Unpack fail, err:", err)
return
}
var csmsg csproto
json.Unmarshal(data_byte, &csmsg)
fmt.Println(msg_id, csmsg)
reivece_msg := cliMsg{
cli,msg_id,data_byte}
ch <- reivece_msg
}
}
func add(data []byte)(int, []byte) {
var csmsg csproto
var scmsg scproto
json.Unmarshal(data, &csmsg)
scmsg.Ans = csmsg.A + csmsg.B
data, err := json.Marshal(scmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
return 0, data
}
func sub(data []byte)(int, []byte) {
var csmsg csproto
var scmsg scproto
fmt.Print("sub")
json.Unmarshal(data, &csmsg)
scmsg.Ans = csmsg.A - csmsg.B
data, err := json.Marshal(scmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
return 1, data
}
func mul(data []byte)(int, []byte) {
var csmsg csproto
var scmsg scproto
json.Unmarshal(data, &csmsg)
scmsg.Ans = csmsg.A * csmsg.B
data, err := json.Marshal(scmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
return 2, data
}
func div(data []byte) (int, []byte) {
var csmsg csproto
var scmsg scproto
json.Unmarshal(data, &csmsg)
if csmsg.B == 0 {
fmt.Println("error, Dividend is zero")
return 10, nil
}
scmsg.Ans = csmsg.A / csmsg.B
data, err := json.Marshal(scmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
return 3, data
}
func handle_data(proch chan cliMsg){
for {
select {
case cli_msg := <- proch:
msg_id, data := cli_msg.msg_id, cli_msg.data
switch {
case msg_id == Add:
cli_msg.msg_id, cli_msg.data = add(data)
case msg_id == Sub:
cli_msg.msg_id, cli_msg.data = sub(data)
case msg_id == Mul:
cli_msg.msg_id, cli_msg.data = mul(data)
case msg_id == Div:
cli_msg.msg_id, cli_msg.data = div(data)
}
proch <- cli_msg
}
}
}
func handle(unch, proch chan cliMsg) {
// 消息转发站,可以省略直接处理
var cli_msg cliMsg
for {
select {
case cli_msg = <-unch: // 收到未处理的信息
proch <- cli_msg // 不会被当前goroutine接收到,发送给 // 先检查其他线程有没有proch接收消息,最后检查当前线程
case cli_msg = <-proch: // 收到已处理的信息
cli_ch := cli_msg.cli.ch
pro_msg := msg{
cli_msg.msg_id, cli_msg.data}
cli_ch <- pro_msg // 发送给对应的send
}
}
}
func TCPServerStart(port string) {
fmt.Println("tcp server start!")
listen, err := Listen("tcp", port)
if err != nil {
fmt.Println("tcp server listen fail, err:", err)
}
unch, proch := make(chan cliMsg, 20), make(chan cliMsg, 20)
go handle(unch, proch)
go handle_data(proch)
for {
conn, err := listen.Accept() // 建立连接
if err != nil {
fmt.Println("server accept fail, err:", err)
continue
}
fmt.Println("connect")
cli_ch := make(chan msg, 20)
cli := client{
cli_ch,conn}
go cli.receive(unch)
go cli.send(cli_ch)
}
}
package Tcp
import (
proto "../tcp_proto"
"bufio"
"encoding/json"
"fmt"
"io"
"net"
)
const (
Quit int = 0
Addc int = 1
Subc int = 2
Mulc int = 3
Divc int = 4
ERROR int = 10
)
var (
chadd chan []byte
chsub chan []byte
chmul chan []byte
chdiv chan []byte
chsend chan msg
)
func sendc(conn net.Conn) {
for {
chsend = make(chan msg, 20)
msg := <- chsend
msg_id := msg.Msg_id
msg_id--
data, err := proto.Packet(msg_id, msg.Data)
if err != nil {
fmt.Println("encode fail, err:", err)
}
conn.Write(data)
}
}
func receivec(conn net.Conn) {
chadd = make(chan []byte, 20)
chsub = make(chan []byte, 20)
chmul = make(chan []byte, 20)
chdiv = make(chan []byte, 20)
defer conn.Close() // 关闭连接
reader := bufio.NewReader(conn)
for {
msg_id, data_byte, err := proto.Unpack(reader)
if err == io.EOF{
return
}
if err != nil{
fmt.Println("Unpack fail, err:", err)
return
}
msg_id++
switch {
case msg_id == Addc:chadd <- data_byte
case msg_id == Subc:chsub <- data_byte
case msg_id == Mulc:chmul <- data_byte
case msg_id == Divc:chdiv <- data_byte
case msg_id == ERROR:// error 处理
}
}
}
func addc() {
for {
fmt.Println("Please enter two addends, enter 0, 0 to return to the previous level")
var a, b, ans int
fmt.Scanf("%d %d", &a, &b)
if a == 0 && b == 0 {
return
}
var csmsg = csproto{
a,b}
csdata, err := json.Marshal(csmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
var msgc = msg{
Addc,csdata}
chsend <- msgc
data := <- chadd
var scmsg scproto
json.Unmarshal(data, &scmsg)
ans = scmsg.Ans
fmt.Printf("%d + %d = %d\n", a, b, ans)
}
}
func subc() {
for {
fmt.Println("Please subtract and subtract, enter 0, 0 to return to the previous level")
var a, b, ans int
fmt.Scanf("%d %d", &a, &b)
if a == 0 && b == 0 {
return
}
var csmsg = csproto{
a,b}
csdata, err := json.Marshal(csmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
var msgc = msg{
Subc,csdata}
chsend <- msgc
data := <- chsub
var scmsg scproto
json.Unmarshal(data, &scmsg)
ans = scmsg.Ans
fmt.Printf("%d - %d = %d\n", a, b, ans)
}
}
func mulc() {
for {
fmt.Println("Please enter two multipliers, enter 0, 0 to return to the previous level")
var a, b, ans int
fmt.Scanf("%d %d", &a, &b)
if a == 0 && b == 0 {
return
}
var csmsg = csproto{
a,b}
csdata, err := json.Marshal(csmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
var msgc = msg{
Mulc,csdata}
chsend <- msgc
data := <- chmul
var scmsg scproto
json.Unmarshal(data, &scmsg)
ans = scmsg.Ans
fmt.Printf("%d * %d = %d\n", a, b, ans)
}
}
func divc() {
for {
fmt.Println("Please divisor and dividend, enter 0, 0 to return to the previous level")
var a, b, ans int
fmt.Scanf("%d %d", &a, &b)
if a == 0 && b == 0 {
return
}
if b == 0 {
fmt.Println("dividend is zero, restart")
continue
}
var csmsg = csproto{
a,b}
csdata, err := json.Marshal(csmsg)
if err != nil {
fmt.Println("encode fail, err:", err)
}
var msgc = msg{
Divc,csdata}
chsend <- msgc
data := <- chdiv
var scmsg scproto
json.Unmarshal(data, &scmsg)
ans = scmsg.Ans
fmt.Printf("%d / %d = %d\n", a, b, ans)
}
}
func TCPClientStrat(addr string) {
conn, err := net.Dial("tcp", addr)
if err != nil {
fmt.Println("connect fail, err:", err)
return
}
defer conn.Close()
go sendc(conn)
go receivec(conn)
for {
fmt.Println("Please choose an operation:")
fmt.Println("1 add\n2 sub\n3 mul\n4 div\n0 quit")
var ot int
fmt.Scanf("%d", &ot)
switch {
case ot == Quit:
return
case ot == Addc:
addc()
break
case ot == Subc:
subc()
break
case ot == Mulc:
mulc()
break
case ot == Divc:
divc()
break
}
}
}
package tcp_proto
import (
"bufio"
"bytes"
"encoding/binary"
"encoding/json"
)
type MsgDate struct {
Msg_id int `json:"msg_id"`
Date []byte `json:"date"`
}
// Encode 将消息编码
func Packet(msg_id int, data []byte)([]byte, error) {
// 读取消息的长度,转换成int32类型(占4个字节)
msg := MsgDate{
msg_id,data}
msg_bytes, err:= json.Marshal(msg)
if err != nil{
return nil, err
}
length := int32(len(msg_bytes))
var pkg = new(bytes.Buffer)
//写入消息头
err = binary.Write(pkg, binary.LittleEndian, length)
if err != nil{
return nil, err
}
//写入消息实体
err = binary.Write(pkg, binary.LittleEndian, msg_bytes)
if err != nil{
return nil, err
}
return pkg.Bytes(), nil
}
// Decode 消息解码
func Unpack(reader *bufio.Reader)(int, []byte, error) {
//读取消息长度
lengthByte, _ := reader.Peek(4) //读取前4个字节数据
lengthBuff := bytes.NewBuffer(lengthByte)
var length int32
err := binary.Read(lengthBuff, binary.LittleEndian, &length)
if err != nil{
return 0, nil, err
}
// Buffered返回缓冲中现有的可读取的字节数。
if int32(reader.Buffered()) < length + 4 {
return 0, nil, err
}
//读取真正的消息数据
pack := make([]byte,int(4 + length))
_, err = reader.Read(pack)
if err != nil{
return 0, nil, err
}
var msg MsgDate
json.Unmarshal(pack[4:], &msg)
return msg.Msg_id, msg.Date, nil
}