Last active
May 22, 2018 05:57
-
-
Save 0x1306a94/0fc66b0ebfa0ededf548d68f02ba9e28 to your computer and use it in GitHub Desktop.
go-tcp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"bytes" | |
"encoding/binary" | |
"fmt" | |
"io" | |
"net" | |
"log" | |
"time" | |
"os" | |
) | |
// 自定义协议的组包和拆包 | |
type Packet struct { | |
Version [2]byte | |
Length int16 | |
Data []byte | |
} | |
func (p *Packet) String() string { | |
return fmt.Sprintf("Version: %v Length: %d Data: %s", | |
string(p.Version[:]), p.Length, string(p.Data)) | |
} | |
func (p *Packet) Pack(w io.Writer) { | |
binary.Write(w, binary.BigEndian, p.Version) | |
binary.Write(w, binary.BigEndian, p.Length) | |
binary.Write(w, binary.BigEndian, p.Data) | |
} | |
func (p *Packet) Unpack(r io.Reader) { | |
binary.Read(r, binary.BigEndian, &p.Version) | |
binary.Read(r, binary.BigEndian, &p.Length) | |
if p.Length > 0 { | |
p.Data = make([]byte, p.Length) | |
} | |
binary.Read(r, binary.BigEndian, &p.Data) | |
} | |
func main() { | |
go startServer() | |
time.Sleep(time.Second * 5) | |
connection() | |
} | |
func startServer() { | |
listen, err := net.Listen("tcp", ":8800") | |
if err != nil { | |
log.Fatal(err) | |
os.Exit(1) | |
} | |
defer listen.Close() | |
for { | |
conn, err := listen.Accept() | |
if err != nil { | |
fmt.Println("Accept error: ", err) | |
continue | |
} | |
go handleConn(conn) | |
} | |
} | |
func connection() { | |
conn, err := net.Dial("tcp", "127.0.0.1:8800") | |
if err != nil { | |
log.Fatal(err) | |
os.Exit(1) | |
} | |
fmt.Println("connection successful...") | |
defer conn.Close() | |
ticker := time.NewTicker(time.Second * 5) | |
idx := 0 | |
for range ticker.C { | |
fmt.Println("send....") | |
idx += 1 | |
var packet Packet | |
packet.Version[0] = 'V' | |
packet.Version[1] = '1' | |
packet.Data = []byte(("index: " + fmt.Sprintf("%d ", idx) + "现在时间是:" + time.Now().Format("2006-01-02 15:04:05"))) | |
packet.Length = int16(len(packet.Data)) | |
buf := new(bytes.Buffer) | |
packet.Pack(buf) | |
packet.Pack(buf) | |
packet.Pack(buf) | |
length, err := conn.Write(buf.Bytes()) | |
if err != nil { | |
fmt.Println("conn write error:", err) | |
continue | |
} else { | |
fmt.Println("conn write successful length:", length) | |
} | |
buf = new(bytes.Buffer) | |
packet.Pack(buf) | |
packet.Pack(buf) | |
packet.Pack(buf) | |
length, err = conn.Write(buf.Bytes()) | |
if err != nil { | |
fmt.Println("conn write error:", err) | |
} else { | |
fmt.Println("conn write successful length:", length) | |
} | |
} | |
} | |
func handleConn(conn net.Conn) { | |
defer conn.Close() | |
// 创建Scanner,分析buf数据流(r io.Reader,换成net.Conn对象就是处理tcp数据流,自己连数据都不需要去收取) | |
scanner := bufio.NewScanner(conn) | |
// 数据的分离规则,根据协议自定义 | |
split := func(data []byte, atEOF bool) (advance int, token []byte, err error) { | |
if !atEOF && data[0] == 'V' { | |
if len(data) > 4 { | |
var dataLen int16 | |
binary.Read(bytes.NewReader(data[2:4]), binary.BigEndian, &dataLen) | |
if int(dataLen)+4 <= len(data) { | |
return int(dataLen) + 4, data[:int(dataLen)+4], nil | |
} | |
} | |
} | |
return | |
} | |
// 设置分离函数 | |
scanner.Split(split) | |
// 获取分离出来的数据 | |
for scanner.Scan() { | |
pac := new(Packet) | |
pac.Unpack(bytes.NewReader(scanner.Bytes())) | |
fmt.Println(pac) | |
} | |
if err := scanner.Err(); err != nil { | |
fmt.Printf("Invalid input: %s", err) | |
} | |
} |
Author
0x1306a94
commented
May 21, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment