dtnat7146
2016-07-28 20:33 阅读 286
已采纳

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 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
    点赞 评论 复制链接分享

相关推荐