Sockets 如何从TCP套接字服务器读取所有数据,然后执行操作
在这上面花了好几个小时之后。我找不到一种方法来读取来自TCP套接字服务器的所有数据,然后进行操作,因为我找不到一种方法来中断循环 套接字服务器发送包含大量以“\n”结尾的行的文本。客户端应该能够读取所有这些行,并使用所有数据发出POST请求,但循环总是挂起,没有办法中断。然后,它将继续等待更多数据,因此停止条件可能是3秒超时 我尝试过不同的解决方案(Scanner、ReadString、ReadLine、ReadAll),但它总是挂起,循环永远不会结束 代码中的最后一行永远不会打印Sockets 如何从TCP套接字服务器读取所有数据,然后执行操作,sockets,go,Sockets,Go,在这上面花了好几个小时之后。我找不到一种方法来读取来自TCP套接字服务器的所有数据,然后进行操作,因为我找不到一种方法来中断循环 套接字服务器发送包含大量以“\n”结尾的行的文本。客户端应该能够读取所有这些行,并使用所有数据发出POST请求,但循环总是挂起,没有办法中断。然后,它将继续等待更多数据,因此停止条件可能是3秒超时 我尝试过不同的解决方案(Scanner、ReadString、ReadLine、ReadAll),但它总是挂起,循环永远不会结束 代码中的最后一行永远不会打印 conn,
conn, err := net.Dial("tcp", "127.0.0.1:15000")
reader := bufio.NewReader(conn)
message := ""
for {
line, err := reader.ReadString('\n')
if err == io.EOF {
break
}
message += line
}
log.Println(message)
如果标准是在收到第一行后超时3秒,则解决方案是在收到第一行后3秒关闭套接字
var firstLineReceived bool
conn, err := net.Dial("tcp", "127.0.0.1:15000")
reader := bufio.NewReader(conn)
message := ""
for {
line, err := reader.ReadString('\n')
if err == io.EOF {
break
}
message += line
if !firstLineReceived {
firstLineReceived = true
go func(){
time.Sleep(3*time.Second)
conn.Close()
}()
}
}
log.Println(message)
如果您唯一的选择是在超时之前读取行,则可以在第一次读取完成后设置连接的读取截止日期。然后,您可以截获超时错误,并将其转换为EOF,以便缓冲读取器正确解释您的意图
type timeoutReader struct {
net.Conn
once sync.Once
}
func (r *timeoutReader) Read(b []byte) (int, error) {
n, err := r.Conn.Read(b)
// Set a read deadline only after the first Read completes
r.once.Do(func() {
r.Conn.SetReadDeadline(time.Now().Add(3 * time.Second))
})
// If we got a timeout, treat it as an io.EOF so the bufio.Scanner handles
// the error as if it was the normal end of the stream.
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return n, io.EOF
}
return n, err
}
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:15000")
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(&timeoutReader{Conn: conn})
message := ""
for scanner.Scan() {
message += scanner.Text()
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
log.Println(message)
}
除非服务器在发送完所有线路后关闭连接,否则永远不会出现io.EOF错误。ReadString将始终阻塞并等待更多数据。要执行您想要执行的操作,服务器应在发送所有线路时关闭连接,或者在完成时需要发送一条特殊线路,以通知客户端在此线路之后没有其他线路。很遗憾,我无法修改服务器。我正在考虑使用goroutine、channel和select。您需要一个标准来确定服务器何时完成发送线路。它可能是行数、没有发送行的延迟等。如果没有此条件,select和GOROUTIES将不会有帮助。一旦我读取第一行,超时3秒。为什么您在读取的同时不执行操作?或者什么是操作类型?对读取本身使用超时不是更适合超时吗?@JimB不确定这是读取超时。OP表示在收到第一行后3秒。在第一行之后可能会收到更多的行,在这种情况下,读取超时将不会具有相同的行为。网络操作使用截止日期,因此
SetReadDeadline(time.Now().Add(3*time.Second))
将在3秒后停止读取。然后您还可以区分EOF、意外关闭和超时。您会得到一个超时错误(请注意,您的示例将进入一个无限循环,因为在读取时关闭连接会返回使用关闭的网络连接,而不是io.EOF
),虽然下面的答案更完整,但这是有效的,但它需要一个for循环来继续阅读更多的文本。