2013-04-28 66 views
0

我正在嘗試爲程序製作套接字管理器。套接字 - 接收確切數量的數據

我的問題是,我需要從套接字檢索一個確切數量的數據到緩衝區。

1)使用靜態數組

製作這樣一個靜態緩衝區爲我工作,但我不能總是知道要接收的數據的大小。

ubyte[2] buffer; 
socket.receive(buffer); 

這是行不通的:

int size = buffer[0]; // for example ... 
ubyte[size] buffer2; // crash at compilation because size is not known 
socket.receive(buffer2); 

所以我的第一個問題是:是否可以有靜態數組沒有在編譯知道它的大小?

我已經搜查了一種使用動態緩衝區,但我已經encoutered其他問題。

2)使用切片從緩衝區

ubyte[] buffer; 
socket.receive(buffer); 
ubyte[2] header = buffer[0..2]; 

這工作,但我怎麼可以從主緩衝區取出提取切片提取數據? 使用從std.algorithm remove函數與一個元組,這樣一來:

buffer = remove(buffer,tuple(0,2)); 

不爲我工作,我不知道爲什麼,我有這樣的錯誤在編譯:

Error: undefined identifier tuple

這裏有什麼問題?

而且,我的插座是非阻塞的,因爲我希望它是異步的。 如果套接字嘗試同時在其上推送數據,那麼在主緩衝區上執行刪除操作會導致問題嗎?

謝謝你看我,對不起我可憐的英語,我不是一個母語的人。

回答

2

警告:我之前沒有使用std.socket,所以這是未經測試的。我有在C插座和經驗,與一般d經驗,但還沒有使用兩者結合起來;)

這就是你想要的猜測,但在這裏有雲:

import std.socket; 
import std.bitmanip; 

Socket socket = new Socket(AddressFamily.INET, SocketType.STREAM); 
// ... bind, connect, etc ... 
ubyte[2] header; 
socket.receive(header); 
ushort size = std.bitmanip.bigEndianToNative!ushort(header); 
ubyte[] content = new ubyte[size]; 
socket.receive(content); 
// ... do your stuff ... 

你即使在運行時,也需要以某種方式知道傳入數據的大小。在我的例子中,大小被封裝在流出的前兩個字節中。使用這些信息,我們動態分配一個緩衝區來保存剩餘的內容。爲了簡單起見,這個例子是同步的:它假定接收將被阻塞直到內容被填充。這個例子也公然忽略了返回值,這是不好的,但我很簡單。

既然你打算做異步通信,您可能需要編寫自己的接收函數調用需要接受多次填充緩衝區,或者如果您已經定義了一些條件不符合中止。

在你的例子1中,問題正是你所期望的:在編譯時沒有辦法在編譯時不知道大小的情況下調整大小(靜態數組)。

那麼你的問題的答案是否定的,在編譯時不知道它們的大小就不可能有靜態數組。

在你的例子2中,「ubyte [] buffer;」在傳入接收之前被初始化爲空。這應該可能會導致斷言崩潰或段錯誤。通常,當D中的一個函數要求緩衝區時,它會期望內存已經被分配;該功能的責任是將已經分配的內存填充所有你想要的東西。唯一的例外可能是如果參數聲明爲ref,ex:「void foo(ref ubyte [] buffer)」,這表明如果你不這樣做,函數將爲你分配緩衝區(需要ref以完成這一點)。這就是爲什麼我的示例在從receive()獲取事物之前進行「新的ubyte [size]」評估。

要獲得關於切片的問題,這是一個骰子數組的簡單方法:

ubyte[] someArray = myArraySource(); 
ubyte[] header = someArray[0 .. 2]; 
someArray = someArray[2 .. $]; // Remove the "header" by slicing out everything else. 

要回答你的最後一個問題:不,這應該不是問題。你應該沒問題。

詳細信息: 對於通過套接字進行雙向通信,我不相信您的緩衝區操作對套接字本身而言很重要。你應該能夠在不影響你的套接字的情況下從主緩衝區中「移除」東西,因爲套接字不會持續對該緩衝區的任何引用。這是你的緩衝區,因爲你分配了它(我希望)。這不取決於套接字的同步性和異步性;只是套接字並不關心你的緩衝區。一旦你收到/發送了你的字節,那麼套接字已經完成了它的工作,至少在下一次被調用之前。

希望有幫助!

+0

謝謝你提供的所有這些信息。我能夠做出一些事情,但仍然存在一個問題:'ubyte [] content = new ubyte [size];'使內容的長度等於大小,所以我無法測試套接字接收到的數據的長度緩衝......有沒有辦法得到它? – Munrek 2013-04-28 17:02:05

+0

這就是爲什麼我的例子調用receive()兩次:一次獲取長度,一次獲取大小的數據。在套接字編程中沒有辦法解決這個問題,除非你可以做出一個好的猜測並在稍後修復它。如果您可以在編譯時進行猜測,那麼執行下列其中一個:'ubyte [sizeGuess] buffer;'或'ubyte [] buffer = new ubyte [sizeGuess];'。例如: ubyte [] buf = new ubyte [sizeGuess]; auto nBytes = socket.receive(buf); assert(nBytes> 2); ushort size = bigEndianToNative!ushort(buf [0..2]); assert(nBytes - 2> = size); //可以更好;) buf = buf [2 .. size + 2]; – chadjoan 2013-04-28 18:28:28

+0

很難在這些評論中格式化代碼。 [http://dpaste.dzfl.pl/fff2cee8](http://dpaste.dzfl.pl/fff2cee8) – chadjoan 2013-04-28 18:37:16

相關問題