2011-10-16 262 views
1

我有兩個小程序通過一個套接字很好地通信,接收端在Go中。當我的信息足夠小以適應1024字節的緩衝區,並且可以從連接中讀取一次,但是現在我想從100k +或更多的圖像傳輸數據時,一切都很好用。我假設正確的解決方案是不增加緩衝區,直到任何圖像可以適應內部。如何通過Go中的套接字檢索文件數據?

僞去:

var buf = make([]byte,1024) 
conn, err := net.Dial("tcp", ":1234") 

for { 
    r, err := conn.Read(buf[0:]) 
    go readHandler(string(buf[0:r]),conn) 
} 

我怎樣才能提高我的套接字讀取程序同時接受簡單的幾個字節的消息,也更大的數據?如果您可以將總圖像數據轉換爲io.Reader以在image.Decode中使用,則可獲得獎勵積分。

回答

2

您可以使用io.ReadFull來讀取特定長度的[]byte。這假定您事先知道需要讀取多少字節。

至於image.Decode,應該可以將conn直接傳遞給image.Decode函數。這假定在圖像解碼之前,您不會從連接執行任何讀取。

您的代碼

for { 
    r, err := conn.Read(buf[0:]) 
    go readHandler(string(buf[0:r]),conn) 
} 

似乎在暗示你開始從conn讀夠程這似乎不是一個好主意,因爲你最終將有多個併發從讀連接(無需控制讀取的順序):一個在for循環中,另一個在readHandler中。

+0

我如何在連接上讀取?是conn.Read一個io.Reader? – Nick

+1

是的,net.Conn實現了io.Reader,因爲net.Conn有「Read(b [] byte)(n int,err os.Error)」方法。 – 2011-10-19 07:23:42

3

我在Go中沒有直接的TCP使用經驗,但對我來說,似乎你成了TCP提供的一種非常典型的誤解的受害者。

事情是,與UDP和SCTP相比,TCP沒有消息邊界的概念,因爲它是面向流的。這意味着,TCP傳輸不透明的字節流,並且很少控制關於接收端的「分塊」流。

我懷疑你發現「發送100k +消息」是發送方的運行時間/網絡庫,通常是通過將你的「消息」消費到其內部緩衝區中,然後以任何塊的形式進行流式處理來「欺騙」你的操作系統的TCP堆棧允許它(在無處不在的硬件/軟件上通常大約8k)。接收器獲取該流的片段大小完全未定義;唯一定義的是流中的字節的排序,它被保留。

因此,它可能會變成你不得不考慮你的方法來接收數據。確切方法取決於該數據的性質被流:

  • 最簡單的方式(如果有過的應用程序級協議的控制)通過下面的「消息有效載荷」的長度在一個固定格式的特殊長度字段。然後對整個消息進行分流是一個兩步驟的過程:1)接收多個字節以獲得長度字段,讀取它,檢查值是否正確,然後2)讀取以下多個字節並完成它。
  • 如果您無法控制應用程序級協議,則解析消息變得更加複雜,通常需要某種複雜的狀態機。

欲瞭解更多信息,看看thisthis

+0

我期望得到類似的東西,感謝有用的信息! – Nick