fix:“RawConn 不稳定导致连接被误杀
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,2 @@
|
||||
bin/*
|
||||
|
||||
inbox/*
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
|
||||
Reference in New Issue
Block a user