2 回答

TA貢獻1851條經驗 獲得超3個贊
此答案假定程序的目標是將數(shù)據回顯給客戶端。該答案包括torek和limon評論中的信息。
Read的文檔說
Read 最多將 len(p) 個字節(jié)讀入 p。它返回讀取的字節(jié)數(shù) (0 <= n <= len(p)) 和遇到的任何錯誤。即使 Read 返回 n < len(p),它也可能在調用期間使用所有 p 作為暫存空間。如果某些數(shù)據可用但 len(p) 字節(jié)不可用,則 Read 通常會返回可用的數(shù)據,而不是等待更多數(shù)據。
第二個程序可能不會讀取所有數(shù)據,因為 Read 可以返回可用數(shù)據而不是等待更多數(shù)據。第二個程序可能不會寫入所有數(shù)據,因為 read 可以返回數(shù)據和錯誤。
讓我們關注第一個程序,因為它更正確。該程序可以在一個連接上進行多次讀取和寫入調用,但這不是重用連接。
最好defer c.Close()在函數(shù)的開頭而不是在c.Close()整個函數(shù)中散布調用。defer 確保無論函數(shù)如何退出,連接都會關閉。
func handleConnection(c net.Conn) {
defer c.Close()
buf := make([]byte, 4096)
for {
n, err := c.Read(buf)
if err != nil || n == 0 {
break
}
n, err = c.Write(buf[0:n])
if err != nil {
break
}
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
讀取可以返回一些數(shù)據和錯誤。在處理錯誤之前處理返回的任何數(shù)據:
func handleConnection(c net.Conn) {
defer c.Close()
buf := make([]byte, 4096)
for {
n, er := c.Read(buf)
if n > 0 {
_, ew := c.Write(buf[:n])
if ew != nil {
break
}
}
if er != nil {
break
}
}
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}
使用io.Copy而不是在應用程序中編寫復制邏輯。io.Copy 函數(shù)可以正確獲取所有細節(jié)。此外,io.Copy 可以使用一些較低級別的優(yōu)化來將數(shù)據從一個連接復制到另一個連接。
func handleConnection(c net.Conn) {
defer c.Close()
io.Copy(c, c)
fmt.Printf("Connection from %v closed.\n", c.RemoteAddr())
}

TA貢獻1865條經驗 獲得超7個贊
這兩種方法做不同的事情:
第一種方法讀取一些數(shù)據并將其寫回,直到出現(xiàn)錯誤或讀取到 0 個字節(jié)。
第二種方法讀取一次,將其寫回,然后關閉連接。
第一種方法不會“重用”連接。它正在實現(xiàn)一個簡單的類似回聲的協(xié)議,該協(xié)議一直運行到連接終止。第二種方法回顯一次并關閉連接。
- 2 回答
- 0 關注
- 393 瀏覽
添加回答
舉報