- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在尝试为一些服务器端代码编写单元测试,但我无法确定关闭测试用例。环回 TCP 连接似乎没有正确处理干净关闭。我在一个示例应用程序中重现了这一点,该应用程序同步执行以下操作:
第 4 步成功,没有错误。我试过使用 json.Encoder 和对 TCPConn.Write 的简单调用。我用 WireShark 检查了流量。服务器发送了一个 FIN 数据包,但客户端从来没有这样做(即使有 1s sleep )服务器甚至发送了一个 RST 数据包来响应(4),并且客户端 conn.Write 仍然返回 nil 作为它的错误。
这看起来完全是疯了。我在这里错过了什么吗?当前运行 Go v1.2.1/Darwin
编辑:强制重现
package main
import (
"bufio"
"fmt"
"net"
)
var (
loopback = make(chan string)
shouldClose = make(chan struct{})
didClose = make(chan struct{})
)
func serve(listener *net.TCPListener) {
conn, err := listener.Accept()
if err != nil {
panic(err)
}
s := bufio.NewScanner(conn)
if !s.Scan() {
panic(fmt.Sprint("Failed to scan for line: ", s.Err()))
}
loopback <- s.Text() + "\n"
<-shouldClose
conn.Close()
close(didClose)
if s.Scan() {
panic("Expected error reading from a socket closed on this side")
}
}
func main() {
listener, err := net.ListenTCP("tcp", &net.TCPAddr{})
if err != nil {
panic(err)
}
go serve(listener)
conn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
panic(fmt.Sprint("Dialer got error ", err))
}
oracle := "Mic check\n"
if _, err = conn.Write([]byte(oracle)); err != nil {
panic(fmt.Sprint("Dialer failed to write oracle: ", err))
}
test := <-loopback
if test != oracle {
panic("Server did not receive the value sent by the client")
}
close(shouldClose)
<-didClose
// For giggles, I can also add a <-time.After(500 * time.Millisecond)
if _, err = conn.Write([]byte("This should fail after active disconnect")); err == nil {
panic("Sender 'successfully' wrote to a closed socket")
}
}
最佳答案
这就是主动关闭 TCP 连接的工作原理。当客户端检测到服务器已关闭时,它应该关闭它的一半连接。
在您的情况下,您没有关闭客户端,而是发送了更多数据。这会导致服务器发送 RST 数据包以强制关闭连接,因为收到的消息无效。
如果您仍然不确定,这里是等效的 python 客户端+服务器,它显示相同的行为。 (我发现使用 python 很有帮助,因为它紧密遵循底层 BSD 套接字 API,而不使用 C)
服务器:
import socket, time
server = socket.socket()
server.bind(("127.0.0.1", 9999))
server.listen(1)
sock, addr = server.accept()
msg = sock.recv(1024)
print msg
print "closing"
sock.close()
time.sleep(3)
print "done"
客户:
import socket, time
sock = socket.socket()
sock.connect(("127.0.0.1", 9999))
sock.send("test\n")
time.sleep(1)
print "sending again!"
sock.send("no error here")
time.sleep(1)
print "sending one last time"
sock.send("broken pipe this time")
要正确检测连接上的远程关闭,您应该执行 Read()
,并在返回时查找 io.EOF
错误。
// we technically need to try and read at least one byte,
// or we will get an EOF even if the connection isn't closed.
buff := make([]byte, 1)
if _, err := conn.Read(buff); err != io.EOF {
panic("connection not closed")
}
关于tcp - net.TCPConn 允许在 FIN 数据包后写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23879000/
我有几个 TCPConn 对象。我想运行 goroutine,它会定期检查我的 TCPConns 是否还活着,如果有人死了,我想关闭这些 TCPConn 并从内存中删除。 如何检查 TCPConn 对
我正在用 Golang 编写一个 TCP 客户端。服务器永远不会发送任何回复或任何数据。 一旦我在给定的超时后无法写入,我希望客户端关闭连接。 因此,通过阅读 Conn 中的 SetWriteDead
在套接字或写入器关闭之前,在没有任何换行符或空字节定界符的情况下调用 TCPConn.Write 似乎不会执行任何操作。 在此示例中,我希望 conn.Write 在写入完成后立即触发服务器上的读取,
我遇到了 gob 协议(protocol)问题(或者可能是一般的网络问题,我的知识薄弱),我不明白为什么下面的代码不能正常工作。它只是一个维护开放 TCP 连接并通过它发送多个 gob 的简单示例。该
我正在使用 Go 1.2 并尝试在我的服务器由于输入中的 fatal error 而关闭的套接字上调用 TCPConn.SetLinger(0)。但是,我不知道该怎么做。 net.Listener.A
我在 Mac 上创建了一个简单的 Go 应用程序,用于在 TCP 连接中写入和读取数据。我用过 GAE Go 版本。后来,我把那个程序移植到 Windows 上,我得到了这个错误: Connectio
我试图通过检查 golang TCPConn.Write 返回的错误来检测发送失败,但它是零。我也尝试使用 TCPConn.SetWriteDeadline没有成功。 事情就是这样发生的: 服务器启动
我正在尝试建立一种在运行 Go 的中央服务器和一组物联网设备(也运行 Go)之间进行通信的方法。 对于每个设备,它通过持久的 TCPConn 连接到中央服务器。这些设备位于路由器后面。中央服务器保存该
我正在尝试为一些服务器端代码编写单元测试,但我无法确定关闭测试用例。环回 TCP 连接似乎没有正确处理干净关闭。我在一个示例应用程序中重现了这一点,该应用程序同步执行以下操作: 创建客户端和服务器连接
是否有一个版本的 ioutil.ReadAll 可以读取到 EOF 或读取 n 字节(以先到者为准)? 出于 DOS 的原因,我不能只从 ioutil.ReadAll 转储中取出前 n 个字节。 最佳
我有一个从 TCPListener.acceptTCP 接受的 TCPConn*。我只想获取字符串或 IP 形式的 IP 地址(无端口信息)。实现该目标的正确方法(即最少的转换/字符串操作)是什么?
我正在 golang 中开发 SIP over TCP 模拟服务。传入的 SIP 消息由 '\r\n\r\n' 序列分隔(我现在不关心 SDP)。我想根据该分隔符提取消息并将其发送到处理 gorout
godocs 说: “EOF 是当没有更多输入可用时 Read 返回的错误。函数应该只返回 EOF 以表示输入的正常结束。如果 EOF 在结构化数据流中意外出现,则相应的错误是 ErrUnexpect
在golang中,你会如何处理TCPConn.Read/Write返回的错误?这个document没有说任何关于读/写错误的信息。 最佳答案 TCPConn 上的 Read 和Write 可能会返回您
http://play.golang.org/p/gZo5RqgY4F 我对 io.Copy 方法有疑问。上面的链接将在 Go 1.5 下的第 44 行阻塞。但会在 1.4.2 中通过。我不知道这个问
我试图从与 redis 客户端(一个正在运行 redis-cli 的终端)的 tcp 连接中读取一些消息。然而,Read net 包的命令要求我提供一个 slice 作为参数。每当我给出一个没有长度的
1.我们能否在同一个 net.UDPConn 或 net.TCPConn 对象上从一个线程调用发送并从另一个线程调用接收? 2.我们能否从同一 net.UDPConn 或 net.TCPConn 对象
我是一名优秀的程序员,十分优秀!