Files
goodlink/netstack/svr.go
kony c7bc4b9c4f u
2025-03-28 17:23:38 +08:00

118 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build windows
package netstack
import (
"bytes"
"log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
)
func handleConnection(ep tcpip.Endpoint, wq *waiter.Queue) {
// 确保连接最终关闭
defer ep.Close()
// 创建等待队列用于读取事件通知
// var wq waiter.Queue
// 创建可读事件监听器waiter.Entry
// EventIn: 当端点有数据可读时触发
waitEntry, notifyCh := waiter.NewChannelEntry(waiter.EventIn)
wq.EventRegister(&waitEntry)
// 退出时自动取消事件注册
defer wq.EventUnregister(&waitEntry)
// 连接处理主循环
for {
var buf bytes.Buffer
// 尝试读取数据(非阻塞模式)
_, err := ep.Read(&buf, tcpip.ReadOptions{})
if err != nil {
switch err.(type) {
case *tcpip.ErrWouldBlock: // 处理暂时无数据的情况
<-notifyCh // 等待可读事件通知
continue
case *tcpip.ErrNotConnected: // 处理连接关闭的情况
log.Println("Connection closed") // 打印连接关闭信息
return // 结束连接处理
}
log.Println(err) // 打印错误信息
return // 其他错误直接返回
}
// 回显数据:将接收到的数据原样写回
var r bytes.Reader
r.Reset(buf.Bytes()) // 将缓冲区数据载入读取器
// 写入数据到TCP连接
_, err = ep.Write(&r, tcpip.WriteOptions{})
if err != nil {
return // 写入失败时结束连接
}
}
}
func startTCPServer(s *stack.Stack) {
// 创建事件等待队列用于异步I/O通知
var wq waiter.Queue
// 创建TCP端点相当于socket
// 参数说明:
// - tcp.ProtocolNumber: TCP协议号(6)
// - ipv4.ProtocolNumber: IPv4协议号(0x0800)
// - &wq: 关联的等待队列
ep, err := s.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, &wq)
if err != nil {
panic(err)
}
// 绑定到指定网络接口NIC 1和端口
// NIC: 网络接口控制器编号(虚拟网卡)
if err := ep.Bind(tcpip.FullAddress{
NIC: 1,
// Addr: tcpip.AddrFromSlice(net.ParseIP("192.168.3.3").To4()),
Addr: tcpip.Address{}, // 零值表示所有IP地址
Port: 80,
}); err != nil {
panic(err)
}
// 启动监听,设置最大等待连接队列长度
if err := ep.Listen(10); err != nil {
panic(err)
}
// 持续接受新连接的循环
for {
var addr tcpip.FullAddress
// 非阻塞式接受连接
newEP, waitq, err := ep.Accept(&addr)
if err != nil {
switch err.(type) {
case *tcpip.ErrWouldBlock: // 处理暂时无连接的情况
// 注册读事件监听
waitEntry, notifyCh := waiter.NewChannelEntry(waiter.EventIn)
wq.EventRegister(&waitEntry)
// 阻塞等待直到新连接到达
<-notifyCh
wq.EventUnregister(&waitEntry)
continue
case *tcpip.ErrInvalidEndpointState: // 处理端点状态错误
continue
default:
log.Println(err)
continue
}
}
log.Printf("Accepted connection from %s:%d\n", addr.Addr, addr.Port)
// 获取新连接的端点
go handleConnection(newEP, waitq) // 传递正确的连接端点
}
}