2011-07-22 109 views
5

在我的基於TCP套接字的服務器上,我通過流發送數據包,其中數據包由一個標頭指定數據包中的字節數,然後是該字節數。對於那些熟悉Erlang的人,我只需設置{packet,4}選項。在iOS方面,我有一些代碼看起來是這樣的,假設我想找出流的大小此消息:CocoaAsyncSocket和從套接字讀取數據

[asyncSocket readDataToLength:4 withTimeout:-1 tag:HEADER_TAG]; 

這工作正常及以下的委託方法調用回調函數:

onSocket:didReadData:withTag: 

我圖下一邏輯步驟是找出流的大小,以及我做到這一點與:

UInt32 readLength; 
    [data getBytes:&readLength length:4]; 
    readLength = ntohl(readLength); 

後硬編碼的在服務器側12個字節的串,讀數長度確實我ndeed在客戶端也讀了12,所以迄今爲止都是很好的。我繼續執行以下:

[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 

此時雖然回調onSocket:didReadData:withTag:不再調用。相反超時在讀正在發生,可能是因爲我沒有處理的正確讀取,此委託方法被調用:

- (NSTimeInterval)onSocket:(AsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length 

所以在總體上,服務器發送16個字節,4字節的報頭和12字節二進制流。

我相信這個錯誤是關於我如何使用CocoaAsyncSocket。在瞭解其尺寸後,閱讀其餘部分流程的正確方法是什麼?

**更新**

我改變了我的客戶,它似乎現在工作。問題是,我不明白新解決方案的readDataToLength的意義。這是我改變了我最初的念想:

[socket readDataWithTimeout:-1 tag:HEADER_TAG]; 

現在,在我的回調,我只是做到以下幾點:

- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 
    if (tag == HEADER_TAG) { 
     UInt32 readLength; 
     [data getBytes:&readLength length:4]; 
     readLength = ntohl(readLength); 
     int offset = 4; 
     NSRange range = NSMakeRange(offset, readLength); 
     char buffer[readLength]; 
     [data getBytes:&buffer range:range]; 
     NSLog(@"buffer %s", buffer); 
     //[sock readDataToLength:readLength withTimeout:1 tag:MESSAGE_TAG]; 
    } else if (tag == MESSAGE_TAG) { 
     //[sock readDataToLength:4 withTimeout:1 tag:HEADER_TAG]; 
    } 

} 

所以一切都進來爲一體,有效載荷原子。也許這是因爲Erlang {packet,4}的工作原理。我希望是。否則,readDataToLength有什麼意義?沒有辦法在客戶端事先知道消息的長度,那麼使用該方法的好用例是什麼?

回答

1

這取決於你如何從Erlang方面發送,我想。選項{packet, 4}將發送每個數據包,其前綴爲4個字節。 Erlang中的每個發送操作都將導致一個數據包以其長度爲前綴進行發送(最大長度爲4,例如,爲2 Gb)。 Erlang文檔的相關部分用於setting the socket options using inet:setopts/2

我猜數據是從目前從套接字讀取的總累計數據。如果這些數據包含您的整個數據包,那就沒問題。但是,如果沒有,您可能希望繼續使用readDataToLength和其餘數據從套接字進行阻塞讀取。