全球主机交流论坛

标题: 【已解决】有没有golang大手子,问题求解 [打印本页]

作者: zhou    时间: 2024-11-19 17:21
标题: 【已解决】有没有golang大手子,问题求解
本帖最后由 zhou 于 2024-11-20 10:35 编辑

需要真大手子,不懂go的就别乱讲了
net.Conn如何多次Read,仅实现这种方式,不要讲别的(比如读取后保存,如果能实现读取后再放回去也可以)
实现后再跟帖,不要已读乱回 GPT不行! GPT不行! GPT不行!

补一个大概的例子


作者: HOH    时间: 2024-11-19 17:23
golang这么先进的lang难道read不能传大小的吗?
作者: iiii.im    时间: 2024-11-19 17:25
gpt分分钟搞定      
作者: zhou    时间: 2024-11-19 17:27
iiii.im 发表于 2024-11-19 17:25
gpt分分钟搞定

GPT能解决我还来发帖干嘛
作者: 欧阳逍遥    时间: 2024-11-19 17:28
for{

循环读。。。。

}
作者: zhou    时间: 2024-11-19 17:29
欧阳逍遥 发表于 2024-11-19 17:28
for{

循环读。。。。

不行的,读完一次就没了
作者: 欧阳逍遥    时间: 2024-11-19 17:31
本帖最后由 欧阳逍遥 于 2024-11-19 17:33 编辑
zhou 发表于 2024-11-19 17:29
不行的,读完一次就没了


用  conn.Read(buf); 读。 自己实现包头,比如前几个字节 存储包头 长度 包体类型什么的, 后面存包体。
作者: 忘江湖    时间: 2024-11-19 17:32
io.ReadFull


作者: zhou    时间: 2024-11-19 17:33
欧阳逍遥 发表于 2024-11-19 17:31
用  conn.Read(buf); 读。 自己实现包头

不管哪种方式conn读完就没了,后面半句没懂什么意思
作者: zhou    时间: 2024-11-19 17:34
忘江湖 发表于 2024-11-19 17:32
io.ReadFull

当然不行,常见方法都试过了
作者: 欧阳逍遥    时间: 2024-11-19 17:36
zhou 发表于 2024-11-19 17:34
当然不行,常见方法都试过了


。。。gpt 回答太长了。。。 你自己去问

golang 实现一个 服务端 客户端 socket 通讯, 其中包含 包头【包体长度】 包体


回答的很详细。。。 包括服务端和客户端代码。

作者: zhou    时间: 2024-11-19 17:37
欧阳逍遥 发表于 2024-11-19 17:36
。。。gpt 回答太长了。。。 你自己去问

golang 实现一个 服务端 客户端 socket 通讯, 其中包含 包头【 ...

GPT不行的,算了
而且提到的什么包头包体 跟本贴主旨也没啥关系
作者: 迷茫的tom    时间: 2024-11-19 17:48
楼主真的了解并且明白自己的需求是什么吗?
你自己明白多次Read意味着什么吗?多次Read的前提条件是什么你知道吗?
作者: 欧阳逍遥    时间: 2024-11-19 17:50
本帖最后由 欧阳逍遥 于 2024-11-19 17:56 编辑
zhou 发表于 2024-11-19 17:37
GPT不行的,算了
而且提到的什么包头包体 跟本贴主旨也没啥关系


算了。。。 可能我真的不会吧
作者: puper    时间: 2024-11-19 17:52
不可能用一个conn变量做到的
作者: 迷茫的tom    时间: 2024-11-19 17:56
欧阳逍遥 发表于 2024-11-19 17:50
你应该把 服务端 和 客户端代码都贴出来。。。

客户端可以循环读, 但是也要服务端 循环发才行。


他一直只能读一次的原因,很大概率是客户端的问题,客户端不一直发消息,服务端哪里能收到消息噢
但是他自己估计一直在懵逼,因为我推测他连短连接长连接,还有tcp/udp都不清楚,所以你们跟他说什么数据包包头之类他才啥都不知道,甚至连自己在问啥估计都还懵逼着
不过也很正常,谁都是从小白过来的

作者: zhou    时间: 2024-11-19 17:57
puper 发表于 2024-11-19 17:52
不可能用一个conn变量做到的

确实瓶颈了,有没有什么曲线救国的方案呢?
作者: puper    时间: 2024-11-19 17:58
zhou 发表于 2024-11-19 17:57
确实瓶颈了,有没有什么曲线救国的方案呢?

从conn读出来, 分发成你需要的个数
作者: loop321    时间: 2024-11-19 17:59

项目中的代码,可以参考一下:


// 格式化请求参数
// copy 重新写入reqbody 默认写入
func CopyReqAndFormData(req *http.Request, copy ...bool) {
        //获取请求体内容
        bodyBytes, _ := ioutil.ReadAll(req.Body)
        _ = req.Body.Close()
        //将请求体内容重新写入请求体
        req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
        if strings.Index(req.Header.Get("Content-Type"), "json") > -1 {
                _ = ParseJson(req)
        } else {
                _ = req.ParseForm() //格式化请求内容
        }
        //将请求体内容重新写入请求体
        if len(copy) == 0 || copy[0] == false {
                req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
        }
}
作者: 欧阳逍遥    时间: 2024-11-19 17:59
迷茫的tom 发表于 2024-11-19 17:56
他一直只能读一次的原因,很大概率是客户端的问题,客户端不一直发消息,服务端哪里能收到消息噢
但是他 ...

刚看了 代码截图。。。 我选择闭嘴。
作者: zhou    时间: 2024-11-19 18:01
迷茫的tom 发表于 2024-11-19 17:56
他一直只能读一次的原因,很大概率是客户端的问题,客户端不一直发消息,服务端哪里能收到消息噢
但是他 ...

客户端就是只发一次,本贴的目的是在服务端Read两次,请问你有什么高见?????


作者: zhou    时间: 2024-11-19 18:03
loop321 发表于 2024-11-19 17:59
项目中的代码,可以参考一下:

gin是可以这样的。读完再放回去,但是tcp socket没有这样的写法...
作者: 欧阳逍遥    时间: 2024-11-19 18:05
本帖最后由 欧阳逍遥 于 2024-11-19 18:10 编辑
zhou 发表于 2024-11-19 18:01
客户端就是只发一次,本贴的目的是在服务端Read两次,请问你有什么高见?????

...




你这写的完全没有逻辑。。。。  首先你客户端是短连接 发完就 断开了。

你服务端 读取 不用协程处理 conn ??? 你客户端就发了一次。。。 可不就只收到一条。。。

客户端  Write 外面加 循环 ,才是长连接 循环发送。

你这就是啥都不会啊。。。。

或者你这么改就能循环读了。。 但是 读第二条要删掉。。。 因为 永远不可能收到。。。

conn,_:=ln.accept()
go func(){ //读取用协程读
        //读取 逻辑 , 客户端发送 只发送一次 你就只能读一次。。
}
作者: 迷茫的tom    时间: 2024-11-19 18:12
本帖最后由 迷茫的tom 于 2024-11-19 18:15 编辑
zhou 发表于 2024-11-19 18:01
客户端就是只发一次,本贴的目的是在服务端Read两次,请问你有什么高见?????

...


没有啥高见,因为流式io和缓冲区设计的时候就不是给你这样用的,不止是net.Conn,基本大部分主流语言对于都是连接流Read完之后就从缓冲区移除
你的数据你都拿完了,后面的你爱存还是怎么样都是你自己的事情,如果你有十分重要的需求,必须要这么做,你可以重写或者重新实现自己的net.Conn包,然后在读取时,再存回去
最后,我没开玩笑,你应该好好审视自己的需求
作者: acm    时间: 2024-11-19 18:17
当你认为GPT连这种基础的技术问题都解决不了的时候应该先问问自己的问题有没有问题
作者: midori    时间: 2024-11-19 18:41
缓冲区被read了之后就释放了呀 ,为什么要read两次,你不能read一次之后自己缓存起来吗
作者: 哈宝儿    时间: 2024-11-19 18:48
自己搞个缓冲区,想独几次读几次
作者: 哈宝儿    时间: 2024-11-19 18:50
准确的说是,读到的数据用自定义格式 全部打到chan队列,读了再丢回去可以一直读
作者: 哈宝儿    时间: 2024-11-19 18:57
图一中 从Conn读了一次到buffer,那为什么第二次不可以从第一个buffer中复制一份,两次读取的内容不一样吗?我记得TCP这块是要解决粘包问题,一次缓冲区装不下的话,是读不完的  
作者: Mr.Bean    时间: 2024-11-19 19:06
读完没了不是正常?创个变量复制一份不就行
作者: 哈宝儿    时间: 2024-11-19 19:10
Mr.Bean 发表于 2024-11-19 19:06
读完没了不是正常?创个变量复制一份不就行

我估计他想要peekData

package main

import (
        "fmt"
        "io"
        "net"
        "sync"
)

type PeekableConn struct {
        conn   net.Conn
        buffer []byte
        mu     sync.Mutex
}

// NewPeekableConn 返回一个新的 PeekableConn 实例
func NewPeekableConn(conn net.Conn) *PeekableConn {
        return &PeekableConn{conn: conn, buffer: make([]byte, 4096)}
}

// Peek 从连接中读取数据但不移除它
func (p *PeekableConn) Peek(n int) ([]byte, error) {
        p.mu.Lock()
        defer p.mu.Unlock()

        // 先读取数据到 buffer
        nRead, err := p.conn.Read(p.buffer)
        if err != nil && err != io.EOF {
                return nil, err
        }

        // 返回前 n 个字节
        if n > nRead {
                n = nRead
        }
        return p.buffer[:n], nil
}

// Read 读取数据并将其从连接中移除
func (p *PeekableConn) Read(b []byte) (int, error) {
        return p.conn.Read(b)
}

func main() {
        listener, err := net.Listen("tcp", ":8080")
        if err != nil {
                fmt.Println("Error:", err)
                return
        }
        defer listener.Close()

        for {
                conn, err := listener.Accept()
                if err != nil {
                        fmt.Println("Error:", err)
                        continue
                }

                go func(c net.Conn) {
                        defer c.Close()
                        peekableConn := NewPeekableConn(c)

                        // Peek 数据
                        data, err := peekableConn.Peek(10)
                        if err != nil {
                                fmt.Println("Peek Error:", err)
                                return
                        }
                        fmt.Printf("Peeked Data: %s\n", data)

                        // 正常读取数据
                        _, err = peekableConn.Read(data)
                        if err != nil {
                                fmt.Println("Read Error:", err)
                                return
                        }
                        fmt.Printf("Read Data: %s\n", data)
                }(conn)
        }
}

通过对连接的读写进行同步,从而达到既可以“窥视”数据又不影响后续的数据读取
作者: jiuqimax    时间: 2024-11-19 19:13
把socket学了再来问
作者: 忘江湖    时间: 2024-11-19 19:30
zhou 发表于 2024-11-19 17:34
当然不行,常见方法都试过了

tcp socket里面,要么你就自己粘包处理,要么就ReadFull让go给你自动粘包一次性读完所有客户端发来的数据,从你的回帖可以看出你对socket机制确实都不熟悉,所以没法沟通。
作者: zhou    时间: 2024-11-20 10:33
哈宝儿 发表于 2024-11-19 19:10
我估计他想要peekData

package main

感谢大佬提供思路,需求就是这样的,目前已解决!
作者: zhou    时间: 2024-11-20 10:35
本帖最后由 zhou 于 2024-11-20 10:41 编辑

已解决,感谢@哈宝儿  大佬提供思路
参考 stackoverflow: https://stackoverflow.com/questions/26196813/peek-into-conn-without-reading-in-go


我不理解有些人为什么一直GPT GPT的,并且无差别喷懂不懂的,既然你那么懂,倒是给出解决方案啊???在这里无脑就喷我目的是让你显眼吗???
作者: xiuxing    时间: 2024-11-20 10:42
zhou 发表于 2024-11-20 10:35
已解决,感谢@哈宝儿  大佬提供思路
参考 stackoverflow: https://stackoverflow.com/questions/26196813/p ...

大佬,带带
作者: jxhczzz    时间: 2024-11-20 10:47
小佬,带带:@
作者: 哈宝儿    时间: 2024-11-20 12:56
本帖最后由 哈宝儿 于 2024-11-20 13:00 编辑
zhou 发表于 2024-11-20 10:35
已解决,感谢@哈宝儿  大佬提供思路
参考 stackoverflow: https://stackoverflow.com/questions/26196813/p ...


不能怪大家,我觉得你这个描述可能没接触到过这块需求的人应该是联想不到 Peek 。

编程中,这种 对数据源只读不取的方式 通用叫法 PeekData .




欢迎光临 全球主机交流论坛 (https://sunk.eu.org/) Powered by Discuz! X3.4