diff --git a/.gitignore b/.gitignore index 582ec45..275b936 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ bin/* - +inbox/* diff --git a/cmd/internal/transport/tcp_linux.go b/cmd/internal/transport/tcp_linux.go index 4264310..3ccbe10 100644 --- a/cmd/internal/transport/tcp_linux.go +++ b/cmd/internal/transport/tcp_linux.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "strings" "syscall" "time" @@ -150,9 +151,15 @@ func (c *TCPConn) writeFrameLinux(frame []byte) error { } }) if err != nil { + if isRawConnNotPollable(err) { + return writeFullFallback(c.conn, frame[written:]) + } return err } if opErr != nil { + if isRawConnNotPollable(opErr) { + return writeFullFallback(c.conn, frame[written:]) + } return opErr } if written != len(frame) { @@ -367,6 +374,15 @@ func (c *TCPConn) readFullLinux(buf []byte) (int64, error) { firstRXTime = rxTimestamp } if err != nil { + if isRawConnNotPollable(err) { + if fallbackErr := readFullFallback(c.conn, buf[offset:]); fallbackErr != nil { + if errors.Is(fallbackErr, io.EOF) && offset > 0 { + return firstRXTime, io.ErrUnexpectedEOF + } + return firstRXTime, fallbackErr + } + return firstRXTime, nil + } if errors.Is(err, io.EOF) && offset > 0 { return firstRXTime, io.ErrUnexpectedEOF } @@ -460,3 +476,27 @@ func parseSCMTimestampingData(data []byte) int64 { func isWouldBlock(err error) bool { return errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EWOULDBLOCK) } + +func isRawConnNotPollable(err error) bool { + return err != nil && strings.Contains(err.Error(), "not pollable") +} + +func writeFullFallback(w io.Writer, buf []byte) error { + for len(buf) > 0 { + n, err := w.Write(buf) + if err != nil { + return err + } + if n <= 0 { + return io.ErrShortWrite + } + buf = buf[n:] + } + + return nil +} + +func readFullFallback(r io.Reader, buf []byte) error { + _, err := io.ReadFull(r, buf) + return err +} diff --git a/cmd/peer/main.go b/cmd/peer/main.go index 4c9643c..73e2a0c 100644 --- a/cmd/peer/main.go +++ b/cmd/peer/main.go @@ -97,7 +97,7 @@ func main() { } log.Printf("sent file %s to %s", *filePath, *targetPeer) } - + //交互式模式:如果启用了交互式模式,则启动一个 REPL 循环,允许用户在命令行输入多条发送文本或文件的命令,直到用户输入退出命令或接收循环发生错误。如果没有启用交互式模式,则等待接收循环结束,如果接收循环发生错误,则打印错误日志。 if *interactive { if err := runInteractiveShell(client, os.Stdin, os.Stdout, receiveErr); err != nil { log.Printf("interactive shell ended: %v", err) @@ -110,6 +110,7 @@ func main() { } } +// 在终端面板中打印报错和交互消息 func runInteractiveShell(client *peerpkg.Client, in io.Reader, out io.Writer, receiveErr <-chan error) error { printInteractiveHelp(out) lines, inputErr := readInteractiveLines(in, out, fmt.Sprintf("%s> ", client.ID()))