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)
}
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)
}
有疑问加站长微信联系(非本文作者)