dtnat7146
2016-07-28 20:33
浏览 429
已采纳

Golang TCP Client无法从服务器接收数据,在conn.Read()上挂起/阻止

I'm taking a dive into the networking side of Go, and I'd thought I'd start with a TCP Client and Server.

I am able to get the client to connect to the server and send a simple message ("Hello") successfully. However, I can not get the server to send back a response (or the get the client to read the response).

Here is the code.

Server

Address := "localhost:9999"
Addr, err := net.ResolveTCPAddr("tcp", Address)
if err != nil {
    log.Fatal(err)
}

listener, err := net.ListenTCP("tcp", Addr)
if err != nil {
    log.Fatal(err)
}
defer listener.Close()

//server loop
for {
    conn, err := listener.Accept()
    if err != nil {
        continue
    }

    go handle(conn)
}

func handle(c net.Conn) {

    totalBytes, message := connRead(c)
    fmt.Println(c.RemoteAddr())

    fmt.Println(string(message[:totalBytes]))

    c.Write([]byte("Hi"))
    fmt.Println("Replied")
    c.Close()
}

func connRead(c net.Conn) (int, []byte) {
    buffer := make([]byte, 4096)
    totalBytes := 0

    for {
        n, err := c.Read(buffer)
        totalBytes += n
        if err != nil {
            if err != io.EOF {
                log.Printf("Read error: %s", err)
            }
            break
        }

    }
    return totalBytes, buffer
}

Client

    tcpAddr, err := net.ResolveTCPAddr("tcp", "localhost:9999")
    if err != nil {
        log.Fatal(err)
    }
    conn, err := net.DialTCP("tcp", nil, tcpAddr)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    _, err = conn.Write([]byte("Hello"))
    if err != nil {
        log.Fatal(err)
    }

    tBytes, resp := connRead(conn)
    fmt.Println(tBytes)
    fmt.Println(string(resp[:tBytes]))

func connRead(c net.Conn) (int, []byte) {
    buffer := make([]byte, 4096)
    totalBytes := 0

    for {
        fmt.Println("Stuck?")
        n, err := c.Read(buffer)
        fmt.Println("Stuck.")
        totalBytes += n
        fmt.Println(totalBytes)
        if err != nil {
            if err != io.EOF {
                log.Printf("Read error: %s", err)
            }
            break
        }

    }
    return totalBytes, buffer
}

From what I can tell it's not a problem with the server. When I run the client, everything stops right after fmt.Println("Stuck?"). This leads me to belive that it's messing up in the n, err := c.Read(buffer) statement somehow. The server doesn't even print out the messeage length (5) and message ("Hello") untill after I Ctrl-C the client. If I comment out the read and printings in the client, then things run smoothly.

I've tried googling for answers, but nothing has come up.

What am I doing wrong? Am I using conn.Read() wrong in the client?

EDIT:

I actually do have access to Linux, so here are the SIGQUIT dumps for the pertinent functions.

Server

http://pastebin.com/itevngCq

Client

http://pastebin.com/XLiKqkvs

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douhuan6065 2016-07-29 03:27
    已采纳
    for {
        n, err := c.Read(buffer)
        totalBytes += n
        if err != nil {
            if err != io.EOF {
                log.Printf("Read error: %s", err)
            }
            break
        }
    
    }
    

    It is because you are reading from connection till EOF error occurs

    conn.Write([]byte("Hello"))
    

    The above statement won't reach EOF at all until you actually closes the connection

    On pressing ctrl+c client side the connection will be closed, So EOF occurs at server side, That is the reason why it is exiting server side for loop and printing these

    127.0.0.1:****
    Hello
    Replied
    

    If you want to make this work you should not read the connection till EOF

    There are many other alternatives for this

    1. Chose a delimiter and read at the server until the delimiter occurs and respond back after that. Check out this link
    2. Send number of bytes to read from client side before sending the actual message, First read number of bytes to read from the server side and then read those many bytes from the connection
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题