golang:net.Conn:检查conn状态

I encountered a strange behavior of the conn.Read: let's presume that I have a couple of functions for testing net.Conn:

package example

import (
    "io"
    "log"
    "net"
    "os"
    "time"
)

func CheckConn(conn net.Conn) (net.Conn, error) {
    conn.SetReadDeadline(time.Now())
    var one = []byte{}
    _, err := conn.Read(one)
    if err != nil {
        log.Println("Net err: ", err)
    }
    if err == io.EOF {
        return conn, err
    }
    var zero time.Time
    conn.SetReadDeadline(zero)
    return conn, nil
}

func CheckConnWithTimeout(conn net.Conn) (net.Conn, error) {
    ch := make(chan bool, 1)
    defer func() {
        ch <- true
    }()
    go func() {
        select {
        case <-ch:
        case <-time.After(1 * time.Second):
            log.Println("It works too long")
            os.Exit(1)
        }
    }()
    return CheckConn(conn)
}

And I want to implement tests for it, lets start with this one:

package example

import (
    "io"
    "net"
    "testing"
)


func TestClosedConn(t *testing.T) {
    server, client := net.Pipe()
    client.Close()
    defer server.Close()
    _, err := CheckConn(server)
    if err != io.EOF {
        t.Errorf("Not equal:
Expected: %v
actual: %v", io.EOF, err)
    }
}

this works pretty well, we will receive io.EOF from CheckConn function, lets add one more test:

func TestClosedConnAfterWrite(t *testing.T) {
    server, client := net.Pipe()
    go func() {
        client.Write([]byte{0xb})
    }()
    client.Close()
    defer server.Close()
    _, err := CheckConn(server)
    err = nil
    if err != io.EOF {
        t.Errorf("Not equal:
Expected: %v
actual: %v", io.EOF, err)
    }
}

looks like the first test, but we wrote to the client before(?) it was closed.

And this will not pass!

conn.Read will return &errors.errorString{s:"EOF"}, instead of io.EOF, so CheckConn will return error == nil,

It looks so weird!

But let's continue the tests, now I want to check unclosed connections:

func TestActiveConn(t *testing.T) {
       server, client := net.Pipe()
       defer client.Close()
       defer server.Close()
       _, err := CheckConnWithTimeout(server)
       if err != nil {
           t.Errorf("Not equal:
Expected: %v
actual: %v", nil, err)
       }
}

I think you noticed that I use the function with a timeout just because SetReadDeadline will not work in this case(I have no idea why!)

So what is going wrong in last two test cases? Is there a normal way to test the connection? Why SetReadDeadline is not working in this case?

draj840143
draj840143 ->您的第二个测试与其goroutine没有同步,可能要等到测试之后才能运行,是的,但是请看一下错误,这是非常意外的
大约 3 年之前 回复
dongmo9996
dongmo9996 读取0字节不读取,也不保证做任何有用的事情。您的第二个测试与goroutine没有同步,goroutine可能直到测试之后才运行,或者根本不运行,并且遇到的任何错误都将被丢弃。不要试图“检查”连接,而要使用它们并适当地处理错误。
大约 3 年之前 回复
douyi3307
douyi3307 是的,这正是我的工作,我尝试从中轻松读取内容,因此我必须检查所有我的帖子中的错误。
大约 3 年之前 回复
duanduan8439
duanduan8439 您无法检查net.Conn的状态,只需从中读取即可。
大约 3 年之前 回复
dtzd65908
dtzd65908 典型的Go方法是启动goroutine读取连接。使用这种方法,无需将通道状态与读取返回值分开检查。
大约 3 年之前 回复
drqja5919276
drqja5919276 我不会在任何一个选项上打赌)但我增加了时间。请在client.Write之后再登录并确认。一切都没有改变,因此我将其删除以使其更易于阅读。
大约 3 年之前 回复
duanchun1881
duanchun1881 “但是我们在关闭之前给客户写信了。”我敢打赌,相反。
大约 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐