Skip to content

Instantly share code, notes, and snippets.

@SLonger
Last active May 13, 2019 02:43
Show Gist options
  • Save SLonger/1d72e2f6cc3b85643118d7752d249265 to your computer and use it in GitHub Desktop.
Save SLonger/1d72e2f6cc3b85643118d7752d249265 to your computer and use it in GitHub Desktop.
tcp 粘包处理 server
// 参考链接https://feixiao.github.io/2016/05/08/bufio/
package main
import (
"bytes"
"encoding/binary"
"flag"
"fmt"
"io"
"net"
"strconv"
"time"
)
var addr = flag.String("addr", "localhost", "The address to listen to; default is \"\" (all interfaces).")
var port = flag.Int("port", 8000, "The port to listen on; default is 8000.")
type Package struct {
Version [2]int8
Datalen int64
Data []byte
}
func (p *Package) String() string {
return fmt.Sprintf("Version:%d DataLen:%d Data:%s", p.Version, p.Datalen, p.Data)
}
func (p *Package) Pack(w io.Writer) {
binary.Write(w, binary.BigEndian, p.Version)
binary.Write(w, binary.BigEndian, p.Datalen)
binary.Write(w, binary.BigEndian, p.Data)
}
func (p *Package) Unpack(r io.Reader) {
binary.Read(r, binary.BigEndian, &p.Version)
binary.Read(r, binary.BigEndian, &p.Datalen)
if p.Datalen > 0 {
p.Data = make([]byte, p.Datalen)
}
binary.Read(r, binary.BigEndian, &p.Data)
}
func BuildMsg(data []byte) Package {
var pkg Package
pkg.Version[0] = 'V'
pkg.Version[1] = '1'
pkg.Data = data
pkg.Datalen = int64(len(pkg.Data))
fmt.Printf("%+v\n", pkg)
return pkg
}
func main() {
flag.Parse()
fmt.Println("Starting server...")
src := *addr + ":" + strconv.Itoa(*port)
listener, _ := net.Listen("tcp", src)
fmt.Printf("Listening on %s.\n", src)
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("Some connection error: %s\n", err)
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
remoteAddr := conn.RemoteAddr().String()
fmt.Println("Client connected from " + remoteAddr)
ech := make(chan error)
go func(conn net.Conn, ech chan error) {
buf := make([]byte, 10)
_, err := conn.Read(buf)
if err != nil {
ech <- err
}
}(conn, ech)
tick := time.NewTicker(2 * time.Second)
for {
select {
case <-tick.C:
handleMessage(conn)
case err := <-ech:
fmt.Println(err)
break
}
}
fmt.Println("Client at " + remoteAddr + " disconnected.")
}
func handleMessage(conn net.Conn) {
var buf bytes.Buffer
jsonstring := []byte("t")
packmsg := BuildMsg(jsonstring)
fmt.Printf("%v\n", packmsg)
packmsg.Pack(&buf)
conn.Write(buf.Bytes())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment