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

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
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料