我正在尝试在Go中创建服务器和客户端,我已设法与服务器和客户端进行通信。但我遇到的问题是golang中的TCP读取是非阻塞的。 我想知道的是,golang中的读取是否可能像C中的读取一样被阻塞。 谢谢
编辑:
以下是服务器的源代码:
func Init_tcp() *net.TCPListener {
laddr, err := net.ResolveTCPAddr("tcp", ":4243")
if err != nil {
log.Fatal(err)
}
tcp, err := net.ListenTCP("tcp", laddr)
if err != nil {
log.Fatal(err)
}
return tcp
}
func main() {
tcp := Init_tcp()
conn, _ := tcp.Accept()
data := make([]byte, 512)
conn.SetNoDelay(false)
for {
conn.Read(data)
fmt.Println(data)
}
}
和我的客户:
func Init_tcp() *net.TCPConn {
laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:4243")
if err != nil {
log.Fatal(err)
}
tcp, err := net.DialTCP("tcp", nil, laddr)
if err != nil {
log.Fatal(err)
}
return tcp
}
func main() {
tcp := Init_tcp()
tcp.Write([]byte("hello world"))
}
答案 0 :(得分:27)
Reader
可以返回部分数据。从the docs,"如果某些数据可用但不是len(p)字节,则Read会按常规返回可用内容而不是等待更多内容。"
这是任何语言的问题,即使这样的事情在C中适合你:TCP只提供可以随时写入的字节流。根据设计,单个写入可以被分解为多个数据包以进行传输,并且接收器没有内置信号说明单个写入/消息/请求的结束位置。应用程序必须找出自己的信号边界方式。这可能意味着分隔符(\n
)或隐式或显式字节数(HTTP' s Content-Length
是明确的)。
要读取特定数量的输入字节,您需要io.ReadAtLeast
或io.ReadFull
。要读取直到满足任意条件,只要没有错误就应该循环Read
调用。 (然后,您可能希望错误地输入太大的输入以防止错误的客户端占用服务器资源。)如果您要实施基于文本的协议,则应考虑net/textproto
,其中放置{ {3}}在连接前面,以便您可以读取线条。要限制你等待完成阅读的时间长度(以便行为不端的客户端不能永久地悬挂和使用内存等),请查看bufio.Reader
函数{{1名称中的(与Deadline
类型的Timeout
函数相关)。 net
包有助于管理超时,截止日期和取消,例如,如果您编写的复杂服务器将在每次请求时执行许多网络操作,则此功能特别有用。
示例代码可能存在一个不相关但重要的问题:它会丢弃Error
和Read
中的错误。这可能会掩盖简单的问题并使它们很难调试。如果在考虑部分读取后遇到问题,请在询问更多帮助之前检查所有错误。请查看context
,以确保此类错误无法投入生产。