go TCP 测试

lqefn · · 1840 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package main


import (
"fmt"
"net"
"os"
"time"
"encoding/binary"
"bytes"
"compress/zlib"
"io/ioutil"
"runtime"
// "github.com/ugorji/go/codec"
)


var ConnectionCount int = 0


func main() {
runtime.GOMAXPROCS(2)
service := ":1400"
tcpAddr, err := net.ResolveTCPAddr("tcp", service)
checkError(err)
TCPListener, err := net.ListenTCP("tcp", tcpAddr)
defer TCPListener.Close()
checkError(err)


st := time.Now()
fmt.Printf("time:%s\n", time.Now().String())


go func() {
for {
time.Sleep(time.Second * 30)
fmt.Printf("connection count %d\n", ConnectionCount)
}
}()


fmt.Printf("use time:%s\n", time.Now().Sub(st).String())


for {
conn, err := TCPListener.AcceptTCP()
if err != nil {
continue
}
go handleClientConn(ClientConn{conn, map[string]ClientHandler{"register": func(req []byte, res []byte) error  {
res = append(res, req...)
return nil
}}, false})
}
}


func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
}


type DataHeader struct {
DataLen uint32
NameLen uint16
Name string
}
const HeaderLength = 6


type ClientHandler func(request []byte, response []byte) error


type ClientConn struct {
Conn net.Conn
DispatchHandlers map[string]ClientHandler
Done bool
}


func (client *ClientConn)Dispatch(method string, data []byte) {
fmt.Printf("dispatch(%s)", method)
handler, ok := client.DispatchHandlers[method]
if ok && handler != nil {
reader, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
// TODO: handler error
}
uncompressed, err := ioutil.ReadAll(reader)
fmt.Printf("data:%s", uncompressed)


result := make([]byte, 1024)
err = handler(data, result)


if err != nil {
// TODO: handler error
}


fmt.Printf("write back(%s)", result)


binary.Write(client.Conn, binary.BigEndian, uint32(len(result)))
binary.Write(client.Conn, binary.BigEndian, uint16(len(method)))
client.Conn.Write([]byte(method))


n, err := client.Conn.Write(result)
if n != len(result) || err != nil {
fmt.Printf("len:%d, write:%d, err:%s", len(result), n, err)
}
} else {
fmt.Printf("no handler found (%s)", method)
}
}


func (client *ClientConn)ReadPacket() {
conn := client.Conn
buff := bytes.NewBuffer(nil)
chunk := make([]byte, 1024)
header := DataHeader{}


for {
n, err := conn.Read(chunk)
if err != nil {
fmt.Printf("err:%s", err)
return
}
buff.Write(chunk[:n])


if buff.Len() >= HeaderLength {
binary.Read(buff, binary.BigEndian, &header.DataLen)
binary.Read(buff, binary.BigEndian, &header.NameLen)


for buff.Len() < int(header.NameLen) {
n, err := conn.Read(chunk)
if err != nil {
fmt.Printf("err:%s", err)
return
}
buff.Write(chunk[:n])
}


nameBuf := make([]byte, header.NameLen)


binary.Read(buff, binary.BigEndian, nameBuf)
methodName := string(nameBuf)
fmt.Printf("methodname(%s)\n", methodName)


for buff.Len() < int(header.DataLen) {
n, err := conn.Read(chunk)
if err != nil {
fmt.Printf("err:%s", err)
return
}
buff.Write(chunk[:n])
}


packet := buff.Bytes()[:header.DataLen]
left := buff.Bytes()[header.DataLen:]


buff.Reset()
buff.Write(left)


fmt.Printf("packet(%d:%s)", header.DataLen, packet)
client.Dispatch(methodName, packet)
}
}
}






func handleClientConn(client ClientConn) {
ConnectionCount += 1
defer func() { ConnectionCount -= 1}()


conn := client.Conn


fmt.Printf("conn(%#v) connected\n", conn)
defer conn.Close()


client.ReadPacket()


fmt.Printf("handler conn(%#v) exit\n", conn)
}

有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:lqefn

查看原文:go TCP 测试

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1840 次点击  
加入收藏 微博
下一篇:GO错误
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传