emmm 注册式网络栈不太好写

This commit is contained in:
impact-eintr
2022-12-18 11:17:06 +08:00
parent ba3c3429e0
commit 5b66b2f42d
4 changed files with 126 additions and 31 deletions

View File

@@ -1,7 +1,10 @@
package main package main
import ( import (
"encoding/binary"
"flag" "flag"
"fmt"
"io"
"log" "log"
"net" "net"
"netstack/logger" "netstack/logger"
@@ -133,6 +136,10 @@ func main() {
//logger.SetFlags(logger.TCP) //logger.SetFlags(logger.TCP)
go func() { // echo server go func() { // echo server
//time.Sleep(1 * time.Second)
//pid := Register()
//log.Fatal(pid)
listener := tcpListen(s, proto, addr, localPort) listener := tcpListen(s, proto, addr, localPort)
done <- struct{}{} done <- struct{}{}
for { for {
@@ -143,7 +150,6 @@ func main() {
log.Println("服务端 建立连接") log.Println("服务端 建立连接")
go func() { go func() {
time.Sleep(3 * time.Second)
for { for {
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
buf := make([]byte, 1024) buf := make([]byte, 1024)
@@ -153,7 +159,7 @@ func main() {
break break
} }
logger.NOTICE(string(buf[:n])) logger.NOTICE(string(buf[:n]))
conn.Write([]byte("Hello Client")) //conn.Write([]byte("Hello Client"))
} }
}() }()
} }
@@ -176,26 +182,80 @@ func main() {
log.Printf("\n\n客户端 写入数据") log.Printf("\n\n客户端 写入数据")
for i := 0; i < 30; i++ { for i := 0; i < 1; i++ {
conn.Write([]byte("Hello Server!")) conn.Write([]byte("Hello Server!"))
buf := make([]byte, 1024) //buf := make([]byte, 1024)
n, err := conn.Read(buf) //n, err := conn.Read(buf)
if err != nil { //if err != nil {
log.Println(err) // log.Println(err)
break // break
} //}
logger.NOTICE(string(buf[:n])) //logger.NOTICE(string(buf[:n]))
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
time.Sleep(500 * time.Minute) select {}
conn.Close() conn.Close()
}() }()
close(done) close(done)
l, err := net.Listen("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
rcv := &RCV{
Stack: s,
rcvBuf: make([]byte, 1<<20),
}
TCPServer(l, rcv)
c := make(chan os.Signal) c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2) signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2)
<-c <-c
} }
const (
REGISTER byte = iota
LISTEN
CONNECT
READ
WRITE
CLOSE
)
// Register 从netstack获取pid
func Register() PID {
// 连接本地netstack服务
conn, err := net.Dial("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println("err : ", err)
return 0
}
defer conn.Close()
_, err = conn.Write(make([]byte, 1<<20))
buf, _ := io.ReadAll(conn)
log.Fatal(buf)
return 3
}
// Listen 传递 pid addr port 监听+绑定地址
func Listen(pid PID, addr tcpip.Address, localPort int) FD {
// 连接本地netstack服务
conn, err := net.Dial("tcp", "127.0.0.1:9999")
if err != nil {
fmt.Println("err : ", err)
return 0
}
buf := make([]byte, 1024)
binary.BigEndian.PutUint16(buf[:4], uint16(pid))
conn.Write(buf)
buf, _ = io.ReadAll(conn)
log.Fatal(buf)
return 0
}

View File

@@ -6,22 +6,28 @@ import (
"io" "io"
"log" "log"
"net" "net"
"netstack/logger"
"netstack/tcpip" "netstack/tcpip"
"netstack/tcpip/header"
"netstack/tcpip/stack" "netstack/tcpip/stack"
"netstack/tcpip/transport/udp"
"netstack/waiter"
"runtime" "runtime"
"strings" "strings"
"sync/atomic"
) )
// PID netstack PID
type PID uint16
var currPID uint32 = 2 // 0 1 2 用过了
type FD uint16
var fds = make(map[PID][1024]FD, 8)
type TCPHandler interface { type TCPHandler interface {
Handle(net.Conn) Handle(net.Conn)
} }
func TCPServer(listener net.Listener, handler TCPHandler) error { func TCPServer(listener net.Listener, handler TCPHandler) error {
log.Printf("netstack 网络解析地址: %s", listener.Addr())
for { for {
clientConn, err := listener.Accept() clientConn, err := listener.Accept()
if err != nil { if err != nil {
@@ -54,31 +60,37 @@ type RCV struct {
} }
func (r *RCV) Handle(conn net.Conn) { func (r *RCV) Handle(conn net.Conn) {
logger.NOTICE("RCV handle")
var err error var err error
r.rcvBuf, err = io.ReadAll(conn) r.rcvBuf, err = io.ReadAll(conn)
if err != nil && len(r.rcvBuf) < 9 { // proto + ip + port if err != nil && len(r.rcvBuf) < 1 { // 操作码
panic(err) panic(err)
} }
switch string(r.rcvBuf[:3]) { logger.NOTICE("注意测试")
case "udp":
var wq waiter.Queue switch r.rcvBuf[0] {
// 新建一个udp端 case REGISTER:
ep, err := r.NewEndpoint(udp.ProtocolNumber, header.IPv4ProtocolNumber, &wq) conn.Write(r.Register())
if err != nil { case LISTEN:
log.Fatal(err) goto FAULT
} case CONNECT:
r.ep = ep goto FAULT
r.Bind() case READ:
r.Connect() goto FAULT
r.Close() case WRITE:
case "tcp": goto FAULT
case CLOSE:
goto FAULT
default: default:
return return
} }
FAULT:
logger.NOTICE("FAULT")
} }
func (r *RCV) Bind() { func (r *RCV) Listen() {
if len(r.rcvBuf) < 9 { // udp ip port if len(r.rcvBuf) < 9 { // udp ip port
log.Println("Error: too few arg") log.Println("Error: too few arg")
return return
@@ -99,3 +111,10 @@ func (r *RCV) Connect() {
func (r *RCV) Close() { func (r *RCV) Close() {
r.ep.Close() r.ep.Close()
} }
func (r *RCV) Register() []byte {
pid := uint16(atomic.AddUint32(&currPID, 1))
b := make([]byte, 2)
binary.BigEndian.PutUint16(b[:2], pid)
return b
}

View File

@@ -1,12 +1,15 @@
package loopback package loopback
import ( import (
"fmt"
"netstack/logger"
"netstack/tcpip" "netstack/tcpip"
"netstack/tcpip/buffer" "netstack/tcpip/buffer"
"netstack/tcpip/stack" "netstack/tcpip/stack"
) )
type endpoint struct { type endpoint struct {
count int
dispatcher stack.NetworkDispatcher dispatcher stack.NetworkDispatcher
} }
@@ -43,6 +46,13 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload b
views = append(views, payload.Views()...) views = append(views, payload.Views()...)
vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views) vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
// TODO 这里整点活 在特定的情况下丢掉数据报 模拟网络阻塞
e.count++
if e.count == 5 || e.count == 7 || e.count == 9 {
logger.NOTICE(fmt.Sprintf("统计 %d 丢掉这个报文", e.count))
return nil
}
// Because we're immediately turning around and writing the packet back to the // Because we're immediately turning around and writing the packet back to the
// rx path, we intentionally don't preserve the remote and local link // rx path, we intentionally don't preserve the remote and local link
// addresses from the stack.Route we're passed. // addresses from the stack.Route we're passed.

View File

@@ -299,3 +299,9 @@ Silly Window Syndrome 翻译成中文就是“糊涂窗口综合症”。正如
1. 要等到 Window Size >= MSS 或是 Data Size >= MSS 1. 要等到 Window Size >= MSS 或是 Data Size >= MSS
2. 收到之前发送数据的 ack 回包,他才会发数据,否则就是在攒数据 2. 收到之前发送数据的 ack 回包,他才会发数据,否则就是在攒数据
> 上面是通过 keepalive 实现的
## tcp的拥塞控制
节介绍 tcp 的拥塞控制,拥塞控制控制是 tcp 协议中最复杂问题之一,主要是如何探测链路已经拥塞?探测到拥塞后如何处理?