2017-06-20 42 views
1

我想從一個Socket向另一個套接字(從ServerSocket創建)發送對應於幾種不同類型(比如說爲了簡單起見,一個float和一個int)的單個數據流接受())。但是,我不確定實現這個目標的最佳方法是什麼。如果我想使用readInt()或readFloat(),我似乎需要分別發送它們,我想這不是理想的(但如果我錯了,請糾正我)。用套接字同時發送多種類型

的代碼會被執行啓動以下(其中說的持股量將被存儲在b中的第4個字節,整型將被存儲在b中的最後4個字節)

ServerSocket socket = new ServerSocket(port); 
in=new DataInputStream(socket.accept().getInputStream()); 

byte[] b = new byte[8]; 
in.read(b); 

所以非常好,但我現在想只將前四個字節轉換爲一個浮點數,最後四個字節轉換爲一個int。我可以做類似

float myFloat = ByteBuffer.wrap(b).getFloat(); 

得到的浮點數,但我怎麼得到int?在C++中,我只是將引用傳遞給b中的第五個元素,但據我所知,這在java中是不可能的。當然,我可以使用一些庫來創建b的最後四個元素的新數組,但是這似乎有點矯枉過勞了?或者是唯一的方法?

有關通過套接字同時發送多種不同類型的其他建議,非常感謝。

+0

爲什麼你不能在你發送的每個值之間使用分隔符(比如換行符)? – nafas

+0

你可以請擴展一下嗎?這聽起來像你想我發送一個字符串,但我不想發送更多的數據比必要的(即我只想發送8個字節,如果可能的話)。 –

+0

如果你已經知道輸入將是4個字節的int和4個字節的float,那麼你可以簡單地按字節準備好字節,並使用前4個爲你的int和下4個爲你的浮點數,如果你需要發送多個值在一起,你需要一個分隔符,只是你知道一個新的行是一個字節(值10) – nafas

回答

1

我想從一個Socket數據[...]單流發送到一個ServerSocket

對不起,是挑剔的,但你不能這樣做。 A ServerSocket是用於接受連接請求並建立基於套接字的通信信道的本地端的機制。該本地端一旦建立,就表示爲Socket,所以你似乎想要做的是將數據從Socket發送到Socket

但你的問題似乎主要是通過通信渠道發送混合數據。在這種情況下,要考慮的第一個問題是接收方如何知道在任何給定點上嘗試讀取什麼類型。這歸結爲在通信方之間建立應用層通信協議。這不一定是正式的或宏偉的;在你的例子中,似乎有一個共同的理解,即數據將作爲32位二進制文​​件float後跟32位二進制文​​件int發送。這是一個協議。

如果我想使用的readInt()或readFloat()看來,我需要分別給他們,我想那會不會是理想的

我不明白你的意思。是的,您確實需要知道哪些數據是int s,哪些是float s,但不區分使用來自任何其他機制的DataInputStream.readInt()DataInputStream.readFloat()

爲您發送的每個數據,你有兩個基本的選擇:在接收

  1. 計數依靠一些事先約定或假設,以確定如何解釋數據(可能延伸到承認的邊界其在線表示)或

  2. 以及數據,發送接收器將用來解釋數據的元數據。

當然,(2)可以看作是(1)的特例。

如果消息總是由一個浮動後面是一個整型,然後我看不出使用

myDataOutputStream.writeFloat(f); 
myDataOutputStream.writeInt(i); 

和接收處理什麼不好的發件人通過

myDataInputStream.readFloat(f); 
myDataInputStream.readInt(i); 

事實上,對於那種簡單的情況,我認爲這是一個不錯的選擇。

然而,更一般地說,在選擇或設計通信協議時還有許多其他的考慮因素。關於這個話題的一般性討論對於這個場地來說太廣泛了。

+0

謝謝,是的,我的意思是在兩個套接字之間發送數據。是的,我正在考慮一種情況,我知道數據應該以這種特定的格式出現。我擔心的是,如果我先寫writeFloat()然後writeInt(),套接字將分別發送兩個數據,但也許情況並非如此?或者,「同時發送它們」的概念甚至不是一個明確定義的問題?對不起,我對網絡很陌生。 –

+0

@JonathanLindgren,一個通信通道,其端點由套接字表示,只是一個字節序列。 'writeFloat()'和'writeInt()'將分別向該通道寫入一些字節,'readFloat()'和'readInt()'將分別讀取適當的字節數。實際上,所有八個字節或許更多都可能在同一個網絡數據包中發送,但是您並沒有提出任何理由認爲在這種情況下實際上很重要。這些細節在套接字級別上基本上是透明的。 –

0

使用存儲和不同類型的值ObjectInputStream & ObjectOutputStream閱讀&寫的類實例的Serializable包裝類似乎是實現這一目標的最佳途徑。 Herehere是很好的參考。

+0

這需要我們創建一個全新的類來存儲兩個變量,似乎有點不必要?如果我發送全班,它真的只有8個字節嗎? –

+0

不,它不會是8個字節。如果你有8個字節的限制,那麼你可以依次使用writeFloat,writeInt和readFloat,readInt。然而,如果你沒有這樣的約束,那麼這是一個很好的方法來解決這個問題,因爲你可以通過改變類來輕鬆擴展和修改它。 –

+0

不僅將使用Java序列化涉及發送超過8個字節,它將涉及發送*多*超過8個。另外,發送者和接收者都需要具有相關類的定義。至少如果兩端都是用Java編寫的,你可以使它工作,但我並不是一個通用通信協議的串行化大愛好者。 –