开源库evio源码学习
tcp自动识别包的大小
通过创建足够大的字节切片,读取之后,通过下面的n可以知道有数据的长度
n, err := c.conn.Read(packet[:])
if err != nil {
c.conn.SetReadDeadline(time.Time{})
l.ch <- &stderr{c, err}
return
}
// todo: 这个牛逼
fmt.Println("packet解析: ", string(packet[:n]))
l.ch <- &stdin{c, append([]byte{}, packet[:n]...)}
我又把服务器的返回的数据也读取了一下
package main
import (
"context"
"fmt"
"log"
"net"
"time"
)
func main() {
var d net.Dialer
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
conn, err := d.DialContext(ctx, "tcp", "localhost:5000")
if err != nil {
log.Fatalf("Failed to dial: %v", err)
}
defer conn.Close()
data := []byte("茅厕")
if _, err := conn.Write(data); err != nil {
log.Fatal(err)
}
data2 := make([]byte, 300)
read, err := conn.Read(data2)
fmt.Println("read", read)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(data2))
fmt.Println(read)
fmt.Println(int(0xFFFF))
}
evio的重要数据结构
// Events represents the server events for the Serve call.
// Each event has an Action return value that is used manage the state
// of the connection and server.
type Events struct {
// NumLoops sets the number of loops to use for the server. Setting this
// to a value greater than 1 will effectively make the server
// multithreaded for multi-core machines. Which means you must take care
// with synchonizing memory between all event callbacks. Setting to 0 or 1
// will run the server single-threaded. Setting to -1 will automatically
// assign this value equal to runtime.NumProcs().
NumLoops int
// LoadBalance sets the load balancing method. Load balancing is always a
// best effort to attempt to distribute the incoming connections between
// multiple loops. This option is only works when NumLoops is set.
LoadBalance LoadBalance
// Serving fires when the server can accept connections. The server
// parameter has information and various utilities.
Serving func(server Server) (action Action)
// Opened fires when a new connection has opened.
// The info parameter has information about the connection such as
// it's local and remote address.
// Use the out return value to write data to the connection.
// The opts return value is used to set connection options.
Opened func(c Conn) (out []byte, opts Options, action Action)
// Closed fires when a connection has closed.
// The err parameter is the last known connection error.
Closed func(c Conn, err error) (action Action)
// Detached fires when a connection has been previously detached.
// Once detached it's up to the receiver of this event to manage the
// state of the connection. The Closed event will not be called for
// this connection.
// The conn parameter is a ReadWriteCloser that represents the
// underlying socket connection. It can be freely used in goroutines
// and should be closed when it's no longer needed.
Detached func(c Conn, rwc io.ReadWriteCloser) (action Action)
// PreWrite fires just before any data is written to any client socket.
PreWrite func()
// Data fires when a connection sends the server data.
// The in parameter is the incoming data.
// Use the out return value to write data to the connection.
Data func(c Conn, in []byte) (out []byte, action Action)
// Tick fires immediately after the server starts and will fire again
// following the duration specified by the delay return value.
Tick func() (delay time.Duration, action Action)
}
type stdserver struct {
events Events // user events
loops []*stdloop // all the loops
lns []*listener // all the listeners
loopwg sync.WaitGroup // loop close waitgroup
lnwg sync.WaitGroup // listener close waitgroup
cond *sync.Cond // shutdown signaler
serr error // signal error
accepted uintptr // accept counter
}
type stdloop struct {
idx int // loop index
ch chan interface{} // command channel
conns map[*stdconn]bool // track all the conns bound to this loop
}
核心就是Data 的注册,接手一条消息就去用chan 通知处理一条,并没有真正的体现epoll