从套接字重复读取

问题描述

开始版本:SELECT disTINCT ON (primary_key_col_1,primary_key_col_2) * FROM edit_d ORDER BY primary_key_col_1,primary_key_col_2,primary_key_col_3 DESC;

TCP服务器

go1.14.4 darwin/amd64

TCP客户端

package main

import (
    "fmt"
    "io"
    "net"
    "time"
)

const (
    maxBufLen int = 4 * 1024
)

type Server struct {
}

func (s *Server) Start() {
    listener,err := net.Listen("tcp","localhost:9001")
    if err != nil {
        panic(err)
    }

    var connections []net.Conn
    defer func() {
        for _,conn := range connections {
            // ignore
            _ = conn.Close()
        }
    }()

    // loop...
    for {
        connected,err := listener.Accept()
        if err != nil {
            if ne,ok := err.(net.Error); ok && ne.Temporary() {
                // temporary err will bi ignored
                continue
            } else {
                fmt.Println(err)
                return
            }
        }

        go handleConn(connected,true)

        connections = append(connections,connected)
    }
}

func handleConn(conn net.Conn,server bool) {
    buf := make([]byte,maxBufLen)

    for {
        // read
        setTimeout(conn)
        _,err := conn.Read(buf)
        if err != nil {
            if ne,ok := err.(net.Error); ok && (ne.Timeout() || ne.Temporary()) {
                fmt.Println("need continue...")
                continue
            }

            if err == io.EOF {
                fmt.Println("EOF")
                break
            }

            // other...
            panic(err)
        }

        // handle recv msg.
        s := string(buf)
        if server {
            //fmt.Println("server recv req ",s)
        } else {
            fmt.Println("client recv resp ",s)
        }

        if server {
            output := "hi " + s
            ob := []byte(output)
            _,err := conn.Write(ob)
            if err != nil {
                fmt.Println(err)
                break
            }
        }
    }
}

func setTimeout(conn net.Conn) {
    setErr := conn.SetReadDeadline(time.Now().Add(20 * time.Second))
    if setErr != nil {
        panic(setErr)
    }
}

主要功能

package main

import (
    "net"
    "time"
)

type Client struct {
    Exit chan struct{}
}

func (c *Client) Start() {
    conn,err := net.Dial("tcp","localhost:9001")
    if err != nil {
        panic(err)
    }

    defer conn.Close()

    go handleWrite(conn)
    go handleConn(conn,false)

    <-c.Exit
}

func handleWrite(conn net.Conn) {
    for {
        input := "carryxyh"
        _,err := conn.Write([]byte(input))
        if err != nil {
            panic(err)
        }

        <-time.After(100 * time.Second)
    }
}

正在运行package main import ( "fmt" "os" "os/signal" "syscall" ) type Starter interface { Start() } func main() { var s Server var c Client go s.Start() go c.Start() sigs := make(chan os.Signal) signal.Notify(sigs,syscall.SIGINT,syscall.SIGTERM) <-sigs c.Exit <- struct{}{} fmt.Println("exit") } 将会打印:

package main

打印两次。但是从程序角度来看,服务器仅向客户端写入一次信息,并且信息的内容应为client recv resp hi carryxyh client recv resp carryxyh 。但是客户除了hi carryxyh之外还打印了carryxyh,这让我很困惑。

在调查过程中,我不小心修改了一行代码,程序立即恢复正常:

modeifycode

如上所述,我修改了服务器响应信息:hi carryxyh => output := "hi "+ s,这时程序仅打印output := "hi "

这使我完全困惑,有人可以帮助我解决这个问题吗?如果有故障排除的主意会更好。

解决方法

enter image description here

这里您忽略了读取的字节长度,可能返回0个字节,你又把buf的内容又回写给客户端了。 _,err:= conn.Read(buf)改成bytesRead,err:= conn.Read(buf); if bytesRead

- 例如:

如果bytesRead == 0 && err == nil { 误差= io.EOF log.Errorf(“ [network] ReadOnce可能总是返回(0,nil)并导致死循环,连接=%d,本地地址=%+ v,远程地址=%+ v”, c.id,c.rawConnection.LocalAddr(),c.RemoteAddr()) }