Google Go在使用Read()函数从连接中读取数据时遇到了EOF。

huangapple go评论110阅读模式
英文:

Google Go EOF on reading from connection using Read()

问题

我正在尝试使用Google Go语言创建一个简单的TCP服务器。我有一个客户端,它指向127.0.0.1:8484。当我的服务器代码尝试读取缓冲区时,我在第37行收到一个EOF错误。客户端发送一个初始的TCP数据包,表示其客户端版本和其他设置(客户端来自游戏,因此我知道我做错了什么)。我正在尝试读取这个数据包。然而,似乎我调用读取的时机太晚了,客户端已经发送了数据包并正在等待响应。任何帮助将不胜感激,因为我真的被难住了。

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. )
  7. func main() {
  8. service := ":8484"
  9. listener, err := net.Listen("tcp", service)
  10. checkError(err)
  11. fmt.Println("Login Server Started\nListening on port:", service[1:])
  12. for {
  13. conn, err := listener.Accept()
  14. if err != nil {
  15. continue
  16. }
  17. go handleClient(conn)
  18. }
  19. }
  20. func handleClient(conn net.Conn) {
  21. const BUFFER_LENGTH = 1024
  22. defer conn.Close()
  23. fmt.Println("Client connected from", conn.RemoteAddr())
  24. var buf [BUFFER_LENGTH]byte
  25. for {
  26. n, err := conn.Read(buf[0:])
  27. if err != nil {
  28. checkError(err)
  29. return
  30. }
  31. _, err2 := conn.Write(buf[0:n])
  32. if err2 != nil {
  33. checkError(err)
  34. return
  35. }
  36. }
  37. }
  38. func checkError(err error) {
  39. if err != nil {
  40. fmt.Fprintf(os.Stderr, "Fatal error: %s\n", err.Error())
  41. os.Exit(1)
  42. }
  43. }

为了更清晰明了,进行了以下修改:

  1. 客户端连接到服务器。
  2. 客户端向服务器发送初始信息,例如客户端版本。
  3. 服务器读取缓冲区。
  4. 服务器响应(目前只是回显缓冲区)。

目前在读取缓冲区阶段出现问题,即n, err := conn.Read(buf[0:])

修复方法:我是个傻瓜,意识到我需要向客户端发送一个握手数据包。

英文:

I am trying to create a simple TCP server using the Google Go language. I have a client which points to 127.0.0.1:8484. When my server code tries to read the buffer I receive an EOF error on line 37. The client sends an initial tcp packet denoting its client version and other settings (the client is from a game therefore I know that I am doing something wrong). I am trying to read this packet. However, it seems I call the read too late and the client has already sent the packet and is waiting for its response. Any help would be appreciated, as I am truly stumped.

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. )
  7. func main() {
  8. service := ":8484"
  9. listener, err := net.Listen("tcp", service)
  10. checkError(err)
  11. fmt.Println("Login Server Started\nListening on port:", service[1:])
  12. for {
  13. conn, err := listener.Accept()
  14. if err != nil {
  15. continue
  16. }
  17. go handleClient(conn)
  18. }
  19. }
  20. func handleClient(conn net.Conn) {
  21. const BUFFER_LENGTH = 1024
  22. defer conn.Close()
  23. fmt.Println("Client connected from", conn.RemoteAddr())
  24. var buf [BUFFER_LENGTH]byte
  25. for {
  26. n, err := conn.Read(buf[0:])
  27. if err != nil {
  28. checkError(err)
  29. return
  30. }
  31. _, err2 := conn.Write(buf[0:n])
  32. if err2 != nil {
  33. checkError(err)
  34. return
  35. }
  36. }
  37. }
  38. func checkError(err error) {
  39. if err != nil {
  40. fmt.Fprintf(os.Stderr, "Fatal error: %s\n", err.Error())
  41. os.Exit(1)
  42. }
  43. }

Edit for clarity:

  1. Client connects to server.
  2. Client sends initial information to server e.g. client version.
  3. Server reads the buffer.
  4. Server responds (currently I am just echoing the buffer).

It is currently failing at the read buffer stage "n, err := conn.Read(buf[0:])".

Fixed: I was being an idiot and realised I needed to send a handshake packet to the client.

答案1

得分: 1

checkError函数中,如果从客户端读取时出现Read()错误,你使用了显式的os.Exit(1),这会导致服务器被终止。

你可以改为:

  1. n, err := conn.Read(buf[0:])
  2. if err != nil {
  3. fmt.Printf(err)
  4. conn.Close()
  5. return
  6. }

这样会在服务器端打印错误信息,并继续监听下一个连接或继续操作。

英文:

Well, in checkError you do an explicit os.Exit(1), which kills your server if there is a Read() error from the client.

Instead of:

  1. n, err := conn.Read(buf[0:])
  2. if err != nil {
  3. checkError(err)
  4. return
  5. }

You can do

  1. n, err := conn.Read(buf[0:])
  2. if err != nil {
  3. fmt.Printf(err)
  4. conn.Close()
  5. return
  6. }

Which will print the error on the server side and will go back to listening for next connection / continue to operate.

答案2

得分: 0

这对我来说是可行的,使用nc命令:

  1. $ nc localhost 8484
  2. 客户端连接来自 127.0.0.1:46464
  3. 你好
  4. 你好
  5. 世界
  6. 世界
  7. ^D
  8. 致命错误:EOF
  9. 退出状态 1

所以我认为你的连接处理没有问题。你可能只是发送了客户端不期望的数据,导致连接关闭。

英文:

This works for me using nc:

  1. $ nc localhost 8484
  2. Client connected from 127.0.0.1:46464
  3. hello
  4. hello
  5. world
  6. world
  7. ^D
  8. Fatal error: EOF
  9. exit status 1

So I think there's nothing wrong with your connection handling. You might just be sending data that the client isn't expecting, and it's closing the connection because of that.

huangapple
  • 本文由 发表于 2014年5月27日 02:05:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/23875617.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定