diff --git a/protocol/etch/README.md b/protocol/etch/README.md new file mode 100644 index 0000000..beb5bb1 --- /dev/null +++ b/protocol/etch/README.md @@ -0,0 +1,13 @@ +Server 建立 TCB,開啟監聽連線,進入狀態 LISTENING +Client 發出連線要求 SYN,進入狀態 SYN-SENT,等待回應 +Server 收到 SYN 要求,回應連線傳送 SYN+ACK,並進入狀態 SYN-RCVD (SYN-RECEIVED) +Client 收到 SYN+ACK 確認完成連線進入狀態 ESTABLISHED,並送出 ACK +Server 收到 ACK 確認連線完成,也進入狀態 ESTABLISHED +雙方開始傳送交換資料 + +Client 準備關閉連線,發出 FIN,進入狀態 FIN-WAIT-1 +Server 收到 FIN,發回收到的 ACK,進入狀態 CLOSE-WAIT,並通知 App 準備斷線 +Client 收到 ACK,進入狀態 FIN-WAIT-2,等待 server 發出 FIN +Server 確認 App 處理完斷線請求,發出 FIN,並進入狀態 LAST-ACK +Client 收到 FIN,並回傳確認的 ACK,進入狀態 TIME-WAIT,等待時間過後正式關閉連線 +Server 收到 ACK,便直接關閉連線 diff --git a/protocol/etch/engine.go b/protocol/etch/engine.go index 6f786e9..0bb35dc 100644 --- a/protocol/etch/engine.go +++ b/protocol/etch/engine.go @@ -1,27 +1,51 @@ package etch import ( + "io" "log" "net" "github.com/mohanson/daze/lib/doa" ) +// Server implemented the etch protocol. type Server struct { + Closer io.Closer Listen string } +// Close listener. +func (s *Server) Close() error { + if s.Closer != nil { + return s.Closer.Close() + } + return nil +} + +// Run it. func (s *Server) Run() error { - addr := doa.Try(net.ResolveUDPAddr("udp", s.Listen)) - conn := doa.Try(net.ListenUDP("udp", addr)) - buf := make([]byte, 512) - for { - n, addr, err := conn.ReadFromUDP(buf) - if err != nil { - break - } - log.Println(addr, string(buf[:n])) + addr, err := net.ResolveUDPAddr("udp", s.Listen) + if err != nil { + return err } + conn, err := net.ListenUDP("udp", addr) + if err != nil { + return err + } + s.Closer = conn + log.Println("main: listen and serve on", s.Listen) + + go func() { + buf := make([]byte, 512) + for { + n, addr, err := conn.ReadFromUDP(buf) + if err != nil { + break + } + log.Println(addr, string(buf[:n])) + } + }() + return nil }