Tcp 谁能告诉我什么';这是golang中io.ReadFull和bytes.Buffer.ReadFrom的行为
我在实现tcp c/s演示时遇到了一个问题,我发现在服务器端使用io.ReadFull(conn,aByteArr)或bytes.Buffer.ReadFrom(conn)时很奇怪。在客户端退出之前,服务器似乎不会读取连接中的数据,换句话说,服务器被阻塞,但我可以使用基本的conn.read(aBuffer)读取数据。为什么这两种方法如此奇怪 因为我希望我的服务器处理任意大小的数据,所以我不喜欢使用基本方法,我是说conn.Read(),它必须先生成一个指定大小的字节片。请帮帮我 我可以给出我的代码: 客户:Tcp 谁能告诉我什么';这是golang中io.ReadFull和bytes.Buffer.ReadFrom的行为,tcp,io,go,byte,buffer,Tcp,Io,Go,Byte,Buffer,我在实现tcp c/s演示时遇到了一个问题,我发现在服务器端使用io.ReadFull(conn,aByteArr)或bytes.Buffer.ReadFrom(conn)时很奇怪。在客户端退出之前,服务器似乎不会读取连接中的数据,换句话说,服务器被阻塞,但我可以使用基本的conn.read(aBuffer)读取数据。为什么这两种方法如此奇怪 因为我希望我的服务器处理任意大小的数据,所以我不喜欢使用基本方法,我是说conn.Read(),它必须先生成一个指定大小的字节片。请帮帮我 我可以给出我的
首先:您永远不会关闭客户端中建立的连接。每次调用send you时,都会呼叫一个新的conn,但绝不刷新或关闭该连接。这似乎很奇怪,可能是这里唯一的问题(例如,如果某一层缓冲你的东西,直到接近或齐平) 似乎您认为应该有一种简单的方法“从某个连接或
io.Reader
读取所有内容”。
没有。如果你对此感到不安,你不应该这样。您希望读取“任意大小的数据”,但任意大小可能意味着418 PB字节。这太多了,可能需要一些时间。我敢打赌,你没有处理这种数据大小的计算能力。读取任意大小的文件基本上需要分块读取,并分块处理,因为您无法处理418 PB的字节
分块阅读是io.Reader提供的功能。它很笨拙。这就是许多协议从数据大小开始的原因:您读取6个字节,如“1423”,解析整数,并知道您的消息长度为1432字节。从那以后,您可以使用提供的便利功能,诸如此类。即使是那些需要EOF
s的,也可能失败
如果您的邮件没有以某些长度指示开头(或长度固定:-),您必须一直阅读到
EOF
。要使此EOF
到达,您必须关闭发送端,否则连接仍处于打开状态,可能会决定在将来发送更多内容。谢谢您的回答,这对我帮助很大。我遵循您的观点,在客户端完成数据发送后关闭连接,尽管还有其他错误,但服务器不再卡住
package main
import (
"net"
"fmt"
"bufio"
"time"
"runtime"
)
func send(s string, ch chan string){
conn, err := net.Dial("tcp", ":4000")
if err != nil {
fmt.Println(err)
}
fmt.Fprintf(conn, s)
fmt.Println("send: ", s)
/*
s := "server run"
conn.Write([]byte(s))
*/
status, err := bufio.NewReader(conn).ReadString('\n')
if err != nil {
fmt.Println("error: ", err)
}
ch <- status
}
func main(){
runtime.GOMAXPROCS(runtime.NumCPU())
fmt.Println("cpu: ", runtime.NumCPU())
ch := make(chan string, 5)
timeout := time.After(10 * time.Second)
i := 0
for{
go send(fmt.Sprintf("%s%d", "client", i), ch)
i++
select {
case ret := <-ch:
fmt.Println(ret)
case <-timeout:
fmt.Println("time out")
return
}
}
}
package main
import (
"net"
"log"
"io"
"fmt"
"time"
//"bytes"
)
func main(){
// Listen on TCP port 2000 on all interfaces.
l, err := net.Listen("tcp", ":4000")
if err != nil {
log.Fatal(err)
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// Handle the connection in a new goroutine.
// The loop then returns to accepting, so that
// multiple connections may be served concurrently.
go func(c net.Conn) {
fmt.Println(c.RemoteAddr())
defer c.Close()
// Echo all incoming data.
/* basic
buf := make([]byte, 100)
c.Read(buf)
fmt.Println(string(buf))
//io.Copy(c, c)
c.Write(buf)
// Shut down the connection.
*/
/* use a ReadFrom
var b bytes.Buffer
b.ReadFrom(conn)
fmt.Println("length: ", b.Len())
c.Write(b.Bytes())
*/
// use io.ReadAll
byteArr := make([]byte, 100)
n, err := io.ReadFull(c, byteArr)
if err != nil {
fmt.Println(err)
}
fmt.Println(n, byteArr[:n], time.Now())
n, _ = c.Write(byteArr[:n])
fmt.Println("write: ", n, time.Now())
}(conn)
}
}