首页 > 解决方案 > 多个串行请求导致空缓冲区

问题描述

在 osx 上的 localhost 上运行的第一个 TCP 连接始终会正确解析发送给它的二进制文件。后续请求丢失二进制数据,只看到第一个字节 [8]。我如何设置阅读器失败?

package main

import (
        "fmt"
        "log"
        "net"
        "os"
        "app/src/internal/handler"

        "github.com/golang-collections/collections/stack"
)

func main() {
        port := os.Getenv("SERVER_PORT")

        s := stack.New()

        ln, err := net.Listen("tcp", ":8080")
        if err != nil {
                log.Fatalf("net.Listen: %v", err)
        }

        fmt.Println("Serving on " + port)

        for {
                conn, err := ln.Accept()
                // defer conn.Close()
                if err != nil {
                        log.Fatal("ln.Accept")
                }
                go handler.Handle(conn, s)

        }
}
package handler

import (
        "fmt"
        "io"
        "log"
        "net"

        "github.com/golang-collections/collections/stack"
)

func Handle(c net.Conn, s *stack.Stack) {
        fmt.Printf("Serving %s\n", c.RemoteAddr().String())

        buf := make([]byte, 0, 256)
        tmp := make([]byte, 128)

        n, err := c.Read(tmp)
        if err != nil {
                if err != io.EOF {
                        log.Fatalf("connection Read() %v", err)
                }
                return
        }

        buf = append(buf, tmp[:n]...)
}

日志:

Serving [::1]:51699
 ------------- value ---------------:QCXhoy5t
Buffer Length: 9. First Value: 8
Serving [::1]:51700
------------- value ---------------:
Buffer Length: 1. First Value: 8
Serving [::1]:51701

测试发送过来:

push random string:
QCXhoy5t

push random string:
GPh0EnbS
push random string:
4kJ0wN0R

标签: gotcpbinarybyte

解决方案


Reader的文档说:

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n 
<= len(p)) and any error encountered. Even if Read returns n < len(p), it may use 
all of p as scratch space during the call. If some data is available but not 
len(p) bytes, Read conventionally returns what is available instead of waiting 
for more.

因此,问题的最可能原因是 Read 正在返回可用的数据(在本例中为单个字符)。您可以通过使用ioutil.ReadAll或在循环中执行读取来解决此问题(数据被添加到缓冲区的事实使它看起来像是最初的意图),例如:

for {
    n, err := c.Read(tmp)
    if err != nil {
        if err != io.EOF {
            // Note that data might have also been received - you should process that
            // if appropriate.
            log.Fatalf("connection Read() %v", err)
            return
        }
        break // All data received so process it
    }
    buf = append(buf, tmp[:n]...)
}

注意:不保证收到任何数据;您应该在尝试访问它之前检查长度(即buf[0]可能会恐慌)


推荐阅读